Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Android 使用PlatformView加载原生播放器时,退入后台,再次进入,页面发生卡顿问题 #2020

Open
xianwenhua opened this issue Apr 19, 2024 · 10 comments
Labels
Android Android Only

Comments

@xianwenhua
Copy link

请描述遇到的问题,以及您所期望的正确的结果

Android 使用PlatformView加载原生播放器时,退入后台,再次进入,Flutter页面发生卡顿问题。

请说明如何操作会遇到上述问题

这个bug修改 019e0affc5e80d9f592f0399fe970b5047357215,再进入后台时,将isNeedHookFlutterDisplay通过反射修改false。
进入前台后 FlutterRenderer 以下代码逻辑不执行。
/**

  • Adds a listener that is invoked whenever this {@code FlutterRenderer} starts and stops painting
  • pixels to an Android {@code View} hierarchy.
    */
    public void addIsDisplayingFlutterUiListener(@nonnull FlutterUiDisplayListener listener) {
    flutterJNI.addIsDisplayingFlutterUiListener(listener);
**if (isDisplayingFlutterUi) {
  listener.onFlutterUiDisplayed();
}**

}
图中标记的代码不会执行,产生问题

在下面填入关键复现代码

**FlutterBoostActivity**

protected void onPause() {
      // ... 省略部分代码
      setIsFlutterUiDisplayed(false)
}

private void setIsFlutterUiDisplayed(boolean isDisplayed) {
        try {
            FlutterRenderer flutterRenderer = this.getFlutterEngine().getRenderer();
            Field isDisplayingFlutterUiField = FlutterRenderer.class.getDeclaredField("isDisplayingFlutterUi");
            isDisplayingFlutterUiField.setAccessible(true);
            isDisplayingFlutterUiField.setBoolean(flutterRenderer, false);

            assert !flutterRenderer.isDisplayingFlutterUi();
        } catch (Exception var4) {
            Log.e("FlutterBoostActivity", "You *should* keep fields in io.flutter.embedding.engine.renderer.FlutterRenderer.");
            var4.printStackTrace();
        }

    }

### 复现的平台

Android

### Flutter SDK版本

3.19.3

### FlutterBoost版本

5.0.1

### 是否延迟初始化FlutterBoost

No

### 解决方案

想了解如果再进入页面时候修改为isDisplayingFlutterUi  = true的情况是否可行。
@joechan-cq
Copy link
Collaborator

用example的image_picker demo选择视频播放能够重现这个问题么?我试了下是正常的

@xianwenhua
Copy link
Author

xianwenhua commented Apr 22, 2024

感谢您的回复,example我测试了,在以下情况下会出现问题:
必现路径为:
1,点击 open flutter page。
2,点击image_picker_demo
3,返回,进入后台
4,出现白屏

另一种问题:
1,点击 open flutter page。
2,点击image_picker_demo。
3,点击键盘弹出,进入后台,再回来,必现列表卡死,无法滚动的情况。

类似上一个问题:
1,点击 open flutter page。
2,点击image_picker_demo,返回,进入后台,再回来,必现列表卡死,无法滚动的情况。

我们遇到的问题,类似下边这种。

@joechan-cq
Copy link
Collaborator

使用Flutter 3.19的SDK,是否参照 #1960 中,使用了临时方案解决兼容问题?

@coderloveryan
Copy link

coderloveryan commented Apr 22, 2024

我也遇到类似问题,临时解决方案也合入了。
我发现有PlatformView时,flutter使用FlutterImageView进行渲染,boost在onPause中将FlutterReneder的isDisplayingFlutterUi属性设为false。推到后台时FlutterJni的onEndFrame触发然后是platformViewsController的onEndFrame方法,该方法内部会执行FlutterView的revertImageView
PrYzFMYoHi
revertImageView方法中调用了render的addIsDisplayingFlutterUiListener方法。该方法会判断isDisplayingFlutterUi的属性值如果为true会回调listener的onFlutterUiDisplayed方法
N94ibp1NeO
listener的回调会执行releaseImageView
yFDpi9mfrZ
但是由于boost在onPause中通过反射更改了改值,造成listener后续不会回调,releaseImageView就不会执行。
tnXILcDFtZ
flutterImageView就会覆盖在flutterTextureView上方界面就不会相应点击、滑动事件。
不知道分析的对不对,麻烦大家一起看看

@joechan-cq
Copy link
Collaborator

@coderloveryan 你这个的现象,就是example里的webview example,再open flutter page后,上个页面的NativeView被带到了下个页面去了吧?这个我重现了。

@coderloveryan
Copy link

coderloveryan commented Apr 22, 2024

@joechan-cq 是的,打开一个新的页面会被带到下一个页面。另外一种情况是如果嵌入的NativeView是视频播放的view,切换后台再切换回来页面由于覆盖了flutterImageView,不会响应事件给用户感觉就是页面卡死。

@joechan-cq joechan-cq removed the waiting for customer response waiting response label Apr 23, 2024
@0xZOne
Copy link
Collaborator

0xZOne commented Apr 24, 2024

官方的PlatformView还有不少问题,例如:

flutter/flutter#113826
flutter/flutter#121687

@joechan-cq
Copy link
Collaborator

joechan-cq commented Apr 24, 2024

PlatformView被带到下个页面,这个我有个疑问,flutter/flutter#113826 里因为attachToView在新容器上重新被调用,所以之前的platformViewsplatformViewParent都被add到了FlutterView上。但对于纯Flutter而言,这些View原本就已经在FlutterView上了,因此FlutterBoost将其重新add到新的FlutterView上的逻辑在我看来没有问题。我跟下来,发现的区别是纯Flutter,打开新页面时,最后触发PlatformViewController中的onBeginFrame->onEndFrame,而FlutterBoost是触发onBeginFrame->onDisplayPlatformView->onEndFrame,这个onDisplayPlatformView就导致currentFrameUsedPlatformViewIds不为空,所以纯Flutter会在onEndFrame中触发finishframe(false),而FlutterBoost不会,且因为isFrameRenderedUsingImageReaders为true,所以platformViewParentView.VISIBLE了,所以显示了出来。 @0xZOne

@0xZOne
Copy link
Collaborator

0xZOne commented Apr 28, 2024

PlatformView被带到下个页面,这个我有个疑问,flutter/flutter#113826 里因为attachToView在新容器上重新被调用,所以之前的platformViewsplatformViewParent都被add到了FlutterView上。但对于纯Flutter而言,这些View原本就已经在FlutterView上了,因此FlutterBoost将其重新add到新的FlutterView上的逻辑在我看来没有问题。我跟下来,发现的区别是纯Flutter,打开新页面时,最后触发PlatformViewController中的onBeginFrame->onEndFrame,而FlutterBoost是触发onBeginFrame->onDisplayPlatformView->onEndFrame,这个onDisplayPlatformView就导致currentFrameUsedPlatformViewIds不为空,所以纯Flutter会在onEndFrame中触发finishframe(false),而FlutterBoost不会,且因为isFrameRenderedUsingImageReaders为true,所以platformViewParentView.VISIBLE了,所以显示了出来。 @0xZOne

这是很久之前提的issue,好久没有看这块代码了:我理解,onDisplayPlatformView这个函数,只要是包含了HC的platformview都会执行才对呀,不管是使用flutterboost的混合应用,还是纯Flutter应用。

@joechan-cq
Copy link
Collaborator

我差不多找到原因了。我去测试了iOS,发现iOS上是好的,那说明Flutter层基本是没有问题的,那问题就出在Native层。

首先onDisplayPlatformView 这个函数,在打开具有platformView或在有platformView的界面刷新时,是会调用的。但是以newContainer=false形式从有platformView的页面到无platformView的页面时(和纯Flutter一样),最后只会触发onBegineFrame->onEndFrame,是不会触发onDisplayPlatformView的。

image

而以newContainer=true形式打开页面,最后的流程是onBegineFrame->onDisplayPlatformView->onEndFrame。所以PlatformView仍然显示了出来,我和之前描述一样。

image

所以我猜想,可能是因为跳转新容器时,在新老容器上detachEngineattachEngine之间存在间隔,导致那几次没有onDisplayPlatformView的流程,没有被Android Java层接收到。所以platformView被add并visible了。于是我尝试将detachEngine和attachEngine的流程,都修改到FlutterBoostActivityonCreate生命周期中,去除中间onResumeonContainerAppeared所产生的间隔,然后再测试,就发现这次newContainer=true打开新容器时,能够接收到丢失了的不包含onDisplayPlatformViewonBeginFrame->onEndFrame流程了,platformView也不会显示到新页面上去了。

image

@joechan-cq joechan-cq added the Android Android Only label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Android Android Only
Projects
None yet
Development

No branches or pull requests

4 participants