Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 6156798

Browse files
author
Emmanuel Garcia
authored
Reland: Create PlatformView instance right after method channel call from Dart (#20568)
1 parent 1801722 commit 6156798

File tree

2 files changed

+221
-94
lines changed

2 files changed

+221
-94
lines changed

shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java

Lines changed: 82 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)