Unverified Commit 0cc7db54 authored by Dan Field's avatar Dan Field Committed by GitHub

Guard against usage after async callbacks in RenderAndroidView, unregister listener (#108496)

parent b1881487
......@@ -109,6 +109,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
/// Sets a new Android view controller.
@override
set controller(AndroidViewController controller) {
assert(!_isDisposed);
assert(_viewController != null);
assert(controller != null);
if (_viewController == controller) {
......@@ -140,6 +141,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
}
void _onPlatformViewCreated(int id) {
assert(!_isDisposed);
markNeedsSemanticsUpdate();
}
......@@ -179,8 +181,14 @@ class RenderAndroidView extends PlatformViewRenderBox {
targetSize = size;
if (_viewController.isCreated) {
_currentTextureSize = await _viewController.setSize(targetSize);
if (_isDisposed) {
return;
}
} else {
await _viewController.create(size: targetSize);
if (_isDisposed) {
return;
}
_currentTextureSize = targetSize;
}
// We've resized the platform view to targetSize, but it is possible that
......@@ -248,6 +256,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
void dispose() {
_isDisposed = true;
_clipRectLayer.layer = null;
_viewController.removeOnPlatformViewCreatedListener(_onPlatformViewCreated);
super.dispose();
}
......
......@@ -221,6 +221,45 @@ void main() {
expect(renderBox.debugLayer!.firstChild, isA<TextureLayer>());
});
});
test('markNeedsPaint does not get called on a disposed RO', () async {
FakeAsync().run((FakeAsync async) {
final AndroidViewController viewController =
PlatformViewsService.initAndroidView(id: 0, viewType: 'webview', layoutDirection: TextDirection.rtl);
final RenderAndroidView renderBox = RenderAndroidView(
viewController: viewController,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{},
);
final Completer<void> viewCreation = Completer<void>();
const MethodChannel channel = MethodChannel('flutter/platform_views');
binding.defaultBinaryMessenger.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
assert(methodCall.method == 'create', 'Unexpected method call');
await viewCreation.future;
return /*textureId=*/ 0;
});
layout(renderBox);
pumpFrame(phase: EnginePhase.paint);
expect(renderBox.debugLayer, isNotNull);
expect(renderBox.debugLayer!.hasChildren, isFalse);
expect(viewController.isCreated, isFalse);
expect(renderBox.debugNeedsPaint, isFalse);
renderBox.dispose();
viewCreation.complete();
async.flushMicrotasks();
expect(viewController.isCreated, isTrue);
expect(renderBox.debugNeedsPaint, isFalse);
expect(renderBox.debugLayer, isNull);
pumpFrame(phase: EnginePhase.paint);
expect(renderBox.debugLayer, isNull);
});
});
}
ui.PointerData _pointerData(
......
......@@ -101,9 +101,7 @@ class FakeAndroidViewController implements AndroidViewController {
}
@override
void removeOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) {
throw UnimplementedError();
}
void removeOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) {}
@override
Future<void> sendMotionEvent(AndroidMotionEvent event) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment