From 3ed16856b3af090d9edf5b0af8518c3614a46036 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Mon, 17 Aug 2020 10:25:21 -0700 Subject: [PATCH] Revert "Create PlatformView instance right after method channel call from Dart (#20500)" This reverts commit 9333b7c1d0ac7b2ae97998df116fcb0f99b1f26f. --- .../platform/PlatformViewsController.java | 86 +++++++++++-------- .../platform/PlatformViewsControllerTest.java | 79 ++++------------- 2 files changed, 65 insertions(+), 100 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index 3c09e57a38d97..7c064a6f90818 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -79,6 +79,7 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega // it is associated with(e.g if a platform view creates other views in the same virtual display. private final HashMap contextToPlatformView; + private final SparseArray platformViewRequests; private final SparseArray platformViews; private final SparseArray mutatorViews; @@ -106,45 +107,18 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega @Override public void createAndroidViewForPlatformView( @NonNull PlatformViewsChannel.PlatformViewCreationRequest request) { - // API level 19 is required for `android.graphics.ImageReader`. + // API level 19 is required for android.graphics.ImageReader. ensureValidAndroidVersion(Build.VERSION_CODES.KITKAT); - - if (!validateDirection(request.direction)) { - throw new IllegalStateException( - "Trying to create a view with unknown direction value: " - + request.direction - + "(view id: " - + request.viewId - + ")"); - } - - final PlatformViewFactory factory = registry.getFactory(request.viewType); - if (factory == null) { - throw new IllegalStateException( - "Trying to create a platform view of unregistered type: " + request.viewType); - } - - Object createParams = null; - if (request.params != null) { - createParams = factory.getCreateArgsCodec().decodeMessage(request.params); - } - - final PlatformView platformView = factory.create(context, request.viewId, createParams); - final View view = platformView.getView(); - if (view == null) { - throw new IllegalStateException( - "PlatformView#getView() returned null, but an Android view reference was expected."); - } - if (view.getParent() != null) { - throw new IllegalStateException( - "The Android view returned from PlatformView#getView() was already added to a parent view."); - } - platformViews.put(request.viewId, view); + platformViewRequests.put(request.viewId, request); } @Override public void disposeAndroidViewForPlatformView(int viewId) { // Hybrid view. + if (platformViewRequests.get(viewId) != null) { + platformViewRequests.remove(viewId); + } + final View platformView = platformViews.get(viewId); if (platformView != null) { final FlutterMutatorView mutatorView = mutatorViews.get(viewId); @@ -404,6 +378,7 @@ public PlatformViewsController() { currentFrameUsedOverlayLayerIds = new HashSet<>(); currentFrameUsedPlatformViewIds = new HashSet<>(); + platformViewRequests = new SparseArray<>(); platformViews = new SparseArray<>(); mutatorViews = new SparseArray<>(); @@ -676,15 +651,50 @@ private void initializeRootImageViewIfNeeded() { @VisibleForTesting void initializePlatformViewIfNeeded(int viewId) { - final View view = platformViews.get(viewId); - if (view == null) { + if (platformViews.get(viewId) != null) { + return; + } + + PlatformViewsChannel.PlatformViewCreationRequest request = platformViewRequests.get(viewId); + if (request == null) { throw new IllegalStateException( "Platform view hasn't been initialized from the platform view channel."); } - if (mutatorViews.get(viewId) != null) { - return; + + if (!validateDirection(request.direction)) { + throw new IllegalStateException( + "Trying to create a view with unknown direction value: " + + request.direction + + "(view id: " + + viewId + + ")"); + } + + PlatformViewFactory factory = registry.getFactory(request.viewType); + if (factory == null) { + throw new IllegalStateException( + "Trying to create a platform view of unregistered type: " + request.viewType); + } + + Object createParams = null; + if (request.params != null) { + createParams = factory.getCreateArgsCodec().decodeMessage(request.params); } - final FlutterMutatorView mutatorView = + + PlatformView platformView = factory.create(context, viewId, createParams); + View view = platformView.getView(); + + if (view == null) { + throw new IllegalStateException( + "PlatformView#getView() returned null, but an Android view reference was expected."); + } + if (view.getParent() != null) { + throw new IllegalStateException( + "The Android view returned from PlatformView#getView() was already added to a parent view."); + } + platformViews.put(viewId, view); + + FlutterMutatorView mutatorView = new FlutterMutatorView( context, context.getResources().getDisplayMetrics().density, androidTouchProcessor); mutatorViews.put(viewId, mutatorView); diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java index 3724666b50e48..659056afc5132 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java @@ -7,7 +7,6 @@ import android.content.Context; import android.content.res.AssetManager; -import android.util.SparseArray; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceHolder; @@ -29,9 +28,7 @@ import io.flutter.embedding.engine.systemchannels.MouseCursorChannel; import io.flutter.embedding.engine.systemchannels.SettingsChannel; import io.flutter.embedding.engine.systemchannels.TextInputChannel; -import io.flutter.plugin.common.FlutterException; import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.StandardMessageCodec; import io.flutter.plugin.common.StandardMethodCodec; import io.flutter.plugin.localization.LocalizationPlugin; import java.nio.ByteBuffer; @@ -245,29 +242,7 @@ public void getPlatformViewById__hybridComposition() { @Test @Config(shadows = {ShadowFlutterJNI.class}) - public void createPlatformViewMessage__initializesAndroidView() { - PlatformViewsController platformViewsController = new PlatformViewsController(); - - int platformViewId = 0; - assertNull(platformViewsController.getPlatformViewById(platformViewId)); - - PlatformViewFactory viewFactory = mock(PlatformViewFactory.class); - PlatformView platformView = mock(PlatformView.class); - when(platformView.getView()).thenReturn(mock(View.class)); - when(viewFactory.create(any(), eq(platformViewId), any())).thenReturn(platformView); - platformViewsController.getRegistry().registerViewFactory("testType", viewFactory); - - FlutterJNI jni = new FlutterJNI(); - attach(jni, platformViewsController); - - // Simulate create call from the framework. - createPlatformView(jni, platformViewsController, platformViewId, "testType"); - verify(platformView, times(1)).getView(); - } - - @Test - @Config(shadows = {ShadowFlutterJNI.class}) - public void createPlatformViewMessage__throwsIfViewIsNull() { + public void initializePlatformViewIfNeeded__throwsIfViewIsNull() { PlatformViewsController platformViewsController = new PlatformViewsController(); int platformViewId = 0; @@ -284,28 +259,22 @@ public void createPlatformViewMessage__throwsIfViewIsNull() { // Simulate create call from the framework. createPlatformView(jni, platformViewsController, platformViewId, "testType"); - assertEquals(ShadowFlutterJNI.getResponses().size(), 1); - final ByteBuffer responseBuffer = ShadowFlutterJNI.getResponses().get(0); - responseBuffer.rewind(); - - StandardMethodCodec methodCodec = new StandardMethodCodec(new StandardMessageCodec()); try { - methodCodec.decodeEnvelope(responseBuffer); - } catch (FlutterException exception) { - assertTrue( - exception - .getMessage() - .contains( - "PlatformView#getView() returned null, but an Android view reference was expected.")); + platformViewsController.initializePlatformViewIfNeeded(platformViewId); + } catch (Exception exception) { + assertTrue(exception instanceof IllegalStateException); + assertEquals( + exception.getMessage(), + "PlatformView#getView() returned null, but an Android view reference was expected."); return; } - assertFalse(true); + assertTrue(false); } @Test @Config(shadows = {ShadowFlutterJNI.class}) - public void createPlatformViewMessage__throwsIfViewHasParent() { + public void initializePlatformViewIfNeeded__throwsIfViewHasParent() { PlatformViewsController platformViewsController = new PlatformViewsController(); int platformViewId = 0; @@ -324,23 +293,16 @@ public void createPlatformViewMessage__throwsIfViewHasParent() { // Simulate create call from the framework. createPlatformView(jni, platformViewsController, platformViewId, "testType"); - assertEquals(ShadowFlutterJNI.getResponses().size(), 1); - - final ByteBuffer responseBuffer = ShadowFlutterJNI.getResponses().get(0); - responseBuffer.rewind(); - - StandardMethodCodec methodCodec = new StandardMethodCodec(new StandardMessageCodec()); try { - methodCodec.decodeEnvelope(responseBuffer); - } catch (FlutterException exception) { - assertTrue( - exception - .getMessage() - .contains( - "The Android view returned from PlatformView#getView() was already added to a parent view.")); + platformViewsController.initializePlatformViewIfNeeded(platformViewId); + } catch (Exception exception) { + assertTrue(exception instanceof IllegalStateException); + assertEquals( + exception.getMessage(), + "The Android view returned from PlatformView#getView() was already added to a parent view."); return; } - assertFalse(true); + assertTrue(false); } @Test @@ -519,7 +481,6 @@ public FlutterImageView createImageView() { @Implements(FlutterJNI.class) public static class ShadowFlutterJNI { - private static SparseArray replies = new SparseArray<>(); public ShadowFlutterJNI() {} @@ -566,13 +527,7 @@ public void setViewportMetrics( @Implementation public void invokePlatformMessageResponseCallback( - int responseId, ByteBuffer message, int position) { - replies.put(responseId, message); - } - - public static SparseArray getResponses() { - return replies; - } + int responseId, ByteBuffer message, int position) {} } @Implements(SurfaceView.class)