@@ -194,13 +194,7 @@ public void onFlutterUiNoLongerDisplayed() {
194
194
}
195
195
};
196
196
197
- private final Consumer <WindowLayoutInfo > windowInfoListener =
198
- new Consumer <WindowLayoutInfo >() {
199
- @ Override
200
- public void accept (WindowLayoutInfo layoutInfo ) {
201
- setWindowInfoListenerDisplayFeatures (layoutInfo );
202
- }
203
- };
197
+ private Consumer <WindowLayoutInfo > windowInfoListener ;
204
198
205
199
/**
206
200
* Constructs a {@code FlutterView} programmatically, without any XML attributes.
@@ -512,6 +506,10 @@ protected void onAttachedToWindow() {
512
506
this .windowInfoRepo = createWindowInfoRepo ();
513
507
Activity activity = ViewUtils .getActivity (getContext ());
514
508
if (windowInfoRepo != null && activity != null ) {
509
+ // Creating windowInfoListener on-demand instead of at initialization is necessary in order to
510
+ // prevent it from capturing the wrong instance of `this` when spying for testing.
511
+ // See https://github.com/mockito/mockito/issues/3479
512
+ windowInfoListener = this ::setWindowInfoListenerDisplayFeatures ;
515
513
windowInfoRepo .addWindowLayoutInfoListener (
516
514
activity , ContextCompat .getMainExecutor (getContext ()), windowInfoListener );
517
515
}
@@ -524,9 +522,10 @@ protected void onAttachedToWindow() {
524
522
*/
525
523
@ Override
526
524
protected void onDetachedFromWindow () {
527
- if (windowInfoRepo != null ) {
525
+ if (windowInfoRepo != null && windowInfoListener != null ) {
528
526
windowInfoRepo .removeWindowLayoutInfoListener (windowInfoListener );
529
527
}
528
+ windowInfoListener = null ;
530
529
this .windowInfoRepo = null ;
531
530
super .onDetachedFromWindow ();
532
531
}
@@ -537,12 +536,12 @@ protected void onDetachedFromWindow() {
537
536
*/
538
537
@ TargetApi (API_LEVELS .API_28 )
539
538
protected void setWindowInfoListenerDisplayFeatures (WindowLayoutInfo layoutInfo ) {
540
- List <DisplayFeature > displayFeatures = layoutInfo .getDisplayFeatures ();
541
- List <FlutterRenderer .DisplayFeature > result = new ArrayList <>();
539
+ List <DisplayFeature > newDisplayFeatures = layoutInfo .getDisplayFeatures ();
540
+ List <FlutterRenderer .DisplayFeature > flutterDisplayFeatures = new ArrayList <>();
542
541
543
542
// Data from WindowInfoTracker display features. Fold and hinge areas are
544
543
// populated here.
545
- for (DisplayFeature displayFeature : displayFeatures ) {
544
+ for (DisplayFeature displayFeature : newDisplayFeatures ) {
546
545
Log .v (
547
546
TAG ,
548
547
"WindowInfoTracker Display Feature reported with bounds = "
@@ -565,31 +564,17 @@ protected void setWindowInfoListenerDisplayFeatures(WindowLayoutInfo layoutInfo)
565
564
} else {
566
565
state = DisplayFeatureState .UNKNOWN ;
567
566
}
568
- result .add (new FlutterRenderer .DisplayFeature (displayFeature .getBounds (), type , state ));
567
+ flutterDisplayFeatures .add (
568
+ new FlutterRenderer .DisplayFeature (displayFeature .getBounds (), type , state ));
569
569
} else {
570
- result .add (
570
+ flutterDisplayFeatures .add (
571
571
new FlutterRenderer .DisplayFeature (
572
572
displayFeature .getBounds (),
573
573
DisplayFeatureType .UNKNOWN ,
574
574
DisplayFeatureState .UNKNOWN ));
575
575
}
576
576
}
577
-
578
- // Data from the DisplayCutout bounds. Cutouts for cameras and other sensors are
579
- // populated here. DisplayCutout was introduced in API 28.
580
- if (Build .VERSION .SDK_INT >= API_LEVELS .API_28 ) {
581
- WindowInsets insets = getRootWindowInsets ();
582
- if (insets != null ) {
583
- DisplayCutout cutout = insets .getDisplayCutout ();
584
- if (cutout != null ) {
585
- for (Rect bounds : cutout .getBoundingRects ()) {
586
- Log .v (TAG , "DisplayCutout area reported with bounds = " + bounds .toString ());
587
- result .add (new FlutterRenderer .DisplayFeature (bounds , DisplayFeatureType .CUTOUT ));
588
- }
589
- }
590
- }
591
- }
592
- viewportMetrics .displayFeatures = result ;
577
+ viewportMetrics .setDisplayFeatures (flutterDisplayFeatures );
593
578
sendViewportMetricsToFlutter ();
594
579
}
595
580
@@ -782,6 +767,22 @@ navigationBarVisible && guessBottomKeyboardInset(insets) == 0
782
767
viewportMetrics .viewInsetLeft = 0 ;
783
768
}
784
769
770
+ // Data from the DisplayCutout bounds. Cutouts for cameras and other sensors are
771
+ // populated here. DisplayCutout was introduced in API 28.
772
+ List <FlutterRenderer .DisplayFeature > displayCutouts = new ArrayList <>();
773
+ if (Build .VERSION .SDK_INT >= API_LEVELS .API_28 ) {
774
+ DisplayCutout cutout = insets .getDisplayCutout ();
775
+ if (cutout != null ) {
776
+ for (Rect bounds : cutout .getBoundingRects ()) {
777
+ Log .v (TAG , "DisplayCutout area reported with bounds = " + bounds .toString ());
778
+ displayCutouts .add (
779
+ new FlutterRenderer .DisplayFeature (
780
+ bounds , DisplayFeatureType .CUTOUT , DisplayFeatureState .UNKNOWN ));
781
+ }
782
+ }
783
+ }
784
+ viewportMetrics .setDisplayCutouts (displayCutouts );
785
+
785
786
// The caption bar inset is a new addition, and the APIs called to query it utilize a list of
786
787
// bounding Rects instead of an Insets object, which is a newer API method, as compared to the
787
788
// existing Insets-based method calls above.
0 commit comments