@@ -79,9 +79,20 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega
7979 // it is associated with(e.g if a platform view creates other views in the same virtual display.
8080 private final HashMap <Context , View > contextToPlatformView ;
8181
82- private final SparseArray <PlatformViewsChannel .PlatformViewCreationRequest > platformViewRequests ;
82+ // The views returned by `PlatformView#getView()`.
83+ //
84+ // This only applies to hybrid composition.
8385 private final SparseArray <View > platformViews ;
84- private final SparseArray <FlutterMutatorView > mutatorViews ;
86+
87+ // The platform view parents that are appended to `FlutterView`.
88+ // If an entry in `platformViews` doesn't have an entry in this array, the platform view isn't
89+ // in the view hierarchy.
90+ //
91+ // This view provides a wrapper that applies scene builder operations to the platform view.
92+ // For example, a transform matrix, or setting opacity on the platform view layer.
93+ //
94+ // This is only applies to hybrid composition.
95+ private final SparseArray <FlutterMutatorView > platformViewParent ;
8596
8697 // Map of unique IDs to views that render overlay layers.
8798 private final SparseArray <FlutterImageView > overlayLayerViews ;
@@ -107,25 +118,57 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega
107118 @ Override
108119 public void createAndroidViewForPlatformView (
109120 @ NonNull PlatformViewsChannel .PlatformViewCreationRequest request ) {
110- // API level 19 is required for android.graphics.ImageReader.
121+ // API level 19 is required for ` android.graphics.ImageReader` .
111122 ensureValidAndroidVersion (Build .VERSION_CODES .KITKAT );
112- platformViewRequests .put (request .viewId , request );
123+
124+ if (!validateDirection (request .direction )) {
125+ throw new IllegalStateException (
126+ "Trying to create a view with unknown direction value: "
127+ + request .direction
128+ + "(view id: "
129+ + request .viewId
130+ + ")" );
131+ }
132+
133+ final PlatformViewFactory factory = registry .getFactory (request .viewType );
134+ if (factory == null ) {
135+ throw new IllegalStateException (
136+ "Trying to create a platform view of unregistered type: " + request .viewType );
137+ }
138+
139+ Object createParams = null ;
140+ if (request .params != null ) {
141+ createParams = factory .getCreateArgsCodec ().decodeMessage (request .params );
142+ }
143+
144+ final PlatformView platformView = factory .create (context , request .viewId , createParams );
145+ final View view = platformView .getView ();
146+ if (view == null ) {
147+ throw new IllegalStateException (
148+ "PlatformView#getView() returned null, but an Android view reference was expected." );
149+ }
150+ if (view .getParent () != null ) {
151+ throw new IllegalStateException (
152+ "The Android view returned from PlatformView#getView() was already added to a parent view." );
153+ }
154+ platformViews .put (request .viewId , view );
113155 }
114156
115157 @ Override
116158 public void disposeAndroidViewForPlatformView (int viewId ) {
117159 // Hybrid view.
118- if (platformViewRequests .get (viewId ) != null ) {
119- platformViewRequests .remove (viewId );
120- }
121-
122160 final View platformView = platformViews .get (viewId );
161+ final FlutterMutatorView parentView = platformViewParent .get (viewId );
123162 if (platformView != null ) {
124- final FlutterMutatorView mutatorView = mutatorViews . get ( viewId );
125- mutatorView .removeView (platformView );
126- (( FlutterView ) flutterView ). removeView ( mutatorView );
163+ if ( parentView != null ) {
164+ parentView .removeView (platformView );
165+ }
127166 platformViews .remove (viewId );
128- mutatorViews .remove (viewId );
167+ }
168+
169+ if (parentView != null ) {
170+ ((FlutterView ) flutterView ).removeView (parentView );
171+ platformViewParent .remove (viewId );
129172 }
130173 }
131174
@@ -378,9 +421,8 @@ public PlatformViewsController() {
378421 currentFrameUsedOverlayLayerIds = new HashSet <>();
379422 currentFrameUsedPlatformViewIds = new HashSet <>();
380423
381- platformViewRequests = new SparseArray <>();
382424 platformViews = new SparseArray <>();
383- mutatorViews = new SparseArray <>();
425+ platformViewParent = new SparseArray <>();
384426
385427 motionEventTracker = MotionEventTracker .getInstance ();
386428 }
@@ -651,55 +693,20 @@ private void initializeRootImageViewIfNeeded() {
651693
652694 @ VisibleForTesting
653695 void initializePlatformViewIfNeeded (int viewId ) {
654- if (platformViews .get (viewId ) != null ) {
655- return ;
656- }
657-
658- PlatformViewsChannel .PlatformViewCreationRequest request = platformViewRequests .get (viewId );
659- if (request == null ) {
660- throw new IllegalStateException (
661- "Platform view hasn't been initialized from the platform view channel." );
662- }
663-
664- if (!validateDirection (request .direction )) {
665- throw new IllegalStateException (
666- "Trying to create a view with unknown direction value: "
667- + request .direction
668- + "(view id: "
669- + viewId
670- + ")" );
671- }
672-
673- PlatformViewFactory factory = registry .getFactory (request .viewType );
674- if (factory == null ) {
675- throw new IllegalStateException (
676- "Trying to create a platform view of unregistered type: " + request .viewType );
677- }
678-
679- Object createParams = null ;
680- if (request .params != null ) {
681- createParams = factory .getCreateArgsCodec ().decodeMessage (request .params );
682- }
683-
684- PlatformView platformView = factory .create (context , viewId , createParams );
685- View view = platformView .getView ();
686-
696+ final View view = platformViews .get (viewId );
687697 if (view == null ) {
688698 throw new IllegalStateException (
689- "PlatformView#getView() returned null, but an Android view reference was expected ." );
699+ "Platform view hasn't been initialized from the platform view channel ." );
690700 }
691- if (view .getParent () != null ) {
692- throw new IllegalStateException (
693- "The Android view returned from PlatformView#getView() was already added to a parent view." );
701+ if (platformViewParent .get (viewId ) != null ) {
702+ return ;
694703 }
695- platformViews .put (viewId , view );
696-
697- FlutterMutatorView mutatorView =
704+ final FlutterMutatorView parentView =
698705 new FlutterMutatorView (
699706 context , context .getResources ().getDisplayMetrics ().density , androidTouchProcessor );
700- mutatorViews .put (viewId , mutatorView );
701- mutatorView .addView (view );
702- ((FlutterView ) flutterView ).addView (mutatorView );
707+ platformViewParent .put (viewId , parentView );
708+ parentView .addView (view );
709+ ((FlutterView ) flutterView ).addView (parentView );
703710 }
704711
705712 public void attachToFlutterRenderer (FlutterRenderer flutterRenderer ) {
@@ -718,13 +725,14 @@ public void onDisplayPlatformView(
718725 initializeRootImageViewIfNeeded ();
719726 initializePlatformViewIfNeeded (viewId );
720727
721- FlutterMutatorView mutatorView = mutatorViews .get (viewId );
722- mutatorView .readyToDisplay (mutatorsStack , x , y , width , height );
723- mutatorView .setVisibility (View .VISIBLE );
724- mutatorView .bringToFront ();
728+ final FlutterMutatorView parentView = platformViewParent .get (viewId );
729+ parentView .readyToDisplay (mutatorsStack , x , y , width , height );
730+ parentView .setVisibility (View .VISIBLE );
731+ parentView .bringToFront ();
725732
726- FrameLayout .LayoutParams layoutParams = new FrameLayout .LayoutParams (viewWidth , viewHeight );
727- View platformView = platformViews .get (viewId );
733+ final FrameLayout .LayoutParams layoutParams =
734+ new FrameLayout .LayoutParams (viewWidth , viewHeight );
735+ final View platformView = platformViews .get (viewId );
728736 platformView .setLayoutParams (layoutParams );
729737 platformView .bringToFront ();
730738 currentFrameUsedPlatformViewIds .add (viewId );
@@ -733,7 +741,7 @@ public void onDisplayPlatformView(
733741 public void onDisplayOverlaySurface (int id , int x , int y , int width , int height ) {
734742 initializeRootImageViewIfNeeded ();
735743
736- FlutterImageView overlayView = overlayLayerViews .get (id );
744+ final FlutterImageView overlayView = overlayLayerViews .get (id );
737745 if (overlayView .getParent () == null ) {
738746 ((FlutterView ) flutterView ).addView (overlayView );
739747 }
@@ -776,19 +784,19 @@ public void onEndFrame() {
776784 // If one of the surfaces doesn't have an image, the frame may be incomplete and must be
777785 // dropped.
778786 // For example, a toolbar widget painted by Flutter may not be rendered.
779- boolean isFrameRenderedUsingImageReaders =
787+ final boolean isFrameRenderedUsingImageReaders =
780788 flutterViewConvertedToImageView && view .acquireLatestImageViewFrame ();
781789 finishFrame (isFrameRenderedUsingImageReaders );
782790 }
783791
784792 private void finishFrame (boolean isFrameRenderedUsingImageReaders ) {
785793 for (int i = 0 ; i < overlayLayerViews .size (); i ++) {
786- int overlayId = overlayLayerViews .keyAt (i );
787- FlutterImageView overlayView = overlayLayerViews .valueAt (i );
794+ final int overlayId = overlayLayerViews .keyAt (i );
795+ final FlutterImageView overlayView = overlayLayerViews .valueAt (i );
788796
789797 if (currentFrameUsedOverlayLayerIds .contains (overlayId )) {
790798 ((FlutterView ) flutterView ).attachOverlaySurfaceToRender (overlayView );
791- boolean didAcquireOverlaySurfaceImage = overlayView .acquireLatestImage ();
799+ final boolean didAcquireOverlaySurfaceImage = overlayView .acquireLatestImage ();
792800 isFrameRenderedUsingImageReaders &= didAcquireOverlaySurfaceImage ;
793801 } else {
794802 // If the background surface isn't rendered by the image view, then the
@@ -802,22 +810,20 @@ private void finishFrame(boolean isFrameRenderedUsingImageReaders) {
802810 }
803811 }
804812
805- for (int i = 0 ; i < platformViews .size (); i ++) {
806- int viewId = platformViews .keyAt (i );
807- View platformView = platformViews .get (viewId );
808- View mutatorView = mutatorViews .get (viewId );
813+ for (int i = 0 ; i < platformViewParent .size (); i ++) {
814+ final int viewId = platformViewParent .keyAt (i );
815+ final View parentView = platformViewParent .get (viewId );
809816
810817 // Show platform views only if the surfaces have images available in this frame,
811818 // and if the platform view is rendered in this frame.
819+ // The platform view is appended to a mutator view.
812820 //
813821 // Otherwise, hide the platform view, but don't remove it from the view hierarchy yet as
814822 // they are removed when the framework diposes the platform view widget.
815823 if (isFrameRenderedUsingImageReaders && currentFrameUsedPlatformViewIds .contains (viewId )) {
816- platformView .setVisibility (View .VISIBLE );
817- mutatorView .setVisibility (View .VISIBLE );
824+ parentView .setVisibility (View .VISIBLE );
818825 } else {
819- platformView .setVisibility (View .GONE );
820- mutatorView .setVisibility (View .GONE );
826+ parentView .setVisibility (View .GONE );
821827 }
822828 }
823829 }
0 commit comments