Sitelet https://github.com/flutter/flutter/issues/190833
Skip to content

RenderAndroidView._setOffset lacks the hasSize guard its sibling gained in #83481 — uncatchable 'RenderBox was not laid out' from its frame callback #190833

Description

@luis-calupet

Steps to reproduce

  1. Embed an Android platform view in virtual-display hosting mode (AndroidView — in our case via mapbox_maps_flutter's MapWidget, default hosting mode).
  2. Mount the widget while a route transition is in flight, so the platform view attaches before the new route's first layout completes.
  3. RenderAndroidView._setOffset's self-rescheduling frame callback runs before the render box has a size.

Expected results

The offset update is skipped (or deferred) until the box is laid out — the same way _handleGlobalPointerEvent in the same class handles it.

Actual results

RenderBox was not laid out: RenderAndroidView#... — in production crash reporting this surfaces with no application frames (frame-callback context), 6 events / 3 users on our closed-test cohort within a week.

Analysis

RenderAndroidView._setOffset (packages/flutter/lib/src/rendering/platform_view.dart:200 at 3.44.6 stable / ee80f08) reschedules itself every frame guarded only by _isDisposed and attached:

void _setOffset() {
  SchedulerBinding.instance.addPostFrameCallback((_) async {
    if (!_isDisposed) {
      if (attached) {
        await _viewController.setOffset(localToGlobal(Offset.zero));
      }
      // Schedule a new post frame callback.
      _setOffset();
    }
  }, debugLabel: 'RenderAndroidView.setOffset');
}

localToGlobal requires completed layout — on an attached-but-unlaid-out box it throws RenderBox was not laid out. Its sibling in the same file, _handleGlobalPointerEvent (line 359), carries exactly the guard _setOffset lacks — added for the same crash class on the iOS side in #83481 (RenderUiKitView._handleGlobalPointerEvent is not checking for null size, closed by adding a hasSize check):

// Don't receive pointer events if not laid out. ...
if (!hasSize) {
  return;
}

So the fix that closed #83481 for pointer events never reached the offset path. Adding the same if (!hasSize) return; (letting the already-scheduled next-frame callback retry after layout) removes the crash without behavior change.

Notes

  • Reproduces on stable; the unguarded code is present at current master.
  • Workaround for map users: androidHostingMode other than virtual display (only VD produces RenderAndroidView), but that is a performance-profile change, not a fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: platform-viewsEmbedding Android/iOS views in Flutter appsc: crashStack traces logged to the consoleplatform-androidAndroid applications specificallyteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework teamwaiting for PR to land (fixed)A fix is in flightworkaround availableThere is a workaround available to overcome the issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions