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]: InAppWebView 加载异常(platformView集成显示异常)(必现) #2161

Open
marchlqq opened this issue Nov 29, 2024 · 25 comments

Comments

@marchlqq
Copy link

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

flutter版本从3.16.9升级到3.24.5(升级到3.19.0,也是一样),
同样的代码,FlutterFragment 显示的 platformView 加载异常。
希望显示正常。

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

出现方式:
1、点击 open flutter fragment page
2、切换 tab
必现。

问题视频:
https://github.com/user-attachments/assets/3db5bae0-58dd-420a-9328-1ebfafce9370

在下面填入关键复现代码

flutter版本从3.16.9升级到3.24.5(升级到3.19.0,也是一样),

InAppWebView 加载的view,50%会加载异常,白屏或者是加载完成以后动不了

代码:
example.zip

复现的平台

Both

Flutter SDK版本

3.24.5

FlutterBoost版本

5.0.1,5.0.2

是否延迟初始化FlutterBoost

No

解决方案

@marchlqq
Copy link
Author

暂时没有思路,感觉跟生命周期也没关系,因为50%的概率显示,感觉那个地方有缓存,第一次加载失败,第二次就重新加载,反复如此。
我对比了加载成功和失败的日志,基本都是一模一样的。调试也没发现太大出入。
之前使用的flutter 3.16.9,显示没有问题。
@0xZOne

@JokerGHit
Copy link

我们项目中遇到了同样的问题 flutter 3.16.9版本没有问题 3.24.5版本 platformView @加载异常,从日志分析没有异常。希望可以提供解决思路 @0xZOne

@joechan-cq
Copy link
Collaborator

joechan-cq commented Dec 2, 2024

可以先设置InAppWebViewSettings里的useHybridComposition参数为false,来解决。
我发现目前FlutterBoost里有关PlatformView的一些异常问题,都是因为useHybridComposition这个玩意儿导致,更里面就是使用了PlatformViewsService.initExpensiveAndroidView导致的。直接使用AndroidView或者PlatformViewsService的其他init方法就没事。

@joechan-cq
Copy link
Collaborator

触发的原因大概查到了,和#1960 的问题一样,都是FlutterTextureViewisPaused变量的问题,这个变量会作为FlutterRender.startRenderingToSurface方法的第二个参数传入,然后这个startRenderingToSurface在3.16和3.19上的区别:

3.16:
image

3.19:
image

可以看到区别在于3.16中最后只会调用flutterJNI.onSurfaceCreated,而3.19会区分调用flutterJNI.onSurfaceCreatedflutterJNI.onSurfaceWindowChanged,然后就和#1960 里一个表现了。

那么再看isPaused为什么是true,是因为触发了FlutterView.convertToImageView方法,里面的renderSurface.pause()使其变成了true
image

@joechan-cq
Copy link
Collaborator

根据Flutter 深入探索混合开发的技术演进这篇文章里面所写,另一种解法是在Flutter层调用

 PlatformViewsService.synchronizeToNativeViewHierarchy(false);

不过我看这个方法在高版本Flutter SDK里已经没了,不过Java层的方法定义还在,因此可以这么写:

SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false);

其实就是不让用FlutterImageView

@marchlqq
Copy link
Author

marchlqq commented Dec 4, 2024

确实,设置了 SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false);
查看的话,少了 FlutterImageView。
对比3.16.9,和3.19.0,设置 Hybrid Composition,view集成方式也出现了变化。

但是,文档也说明了:那为什么会有把 FlutterSurfaceView 变成了 FlutterImageView 这样的操作?原因其实是为了更好的动画同步和渲染效果。

现在去掉了,demo目前看不出有什么问题,项目中还没验证。这里采用 synchronizeToNativeViewHierarchy,去掉,会有什么影响吗?暂时看不出来。

  1. synchronizeToNativeViewHierarchy 方法
    作用: 这个方法用于确保 Flutter 的视图层次结构与原生视图层次结构同步。这在使用 Hybrid Composition 时尤其重要,因为你可能希望 Flutter 渲染的内容与原生 UI 组件无缝集成。
    去掉的影响:
    如果你去掉了 synchronizeToNativeViewHierarchy 的调用,可能会导致 Flutter 渲染的内容与原生视图的层次结构不同步。这可能会影响到视图的交互、动画效果和性能。
    在某些情况下,可能不会立即发现显著问题,但在复杂的 UI 或动画场景中,潜在的问题可能会显现出来

@joechan-cq
Copy link
Collaborator

我的想法是如果PlatformView和Flutter上的UI没有复杂的交叉层级堆叠显示的问题,那么就没必要使用Hybrid模式。
如果想继续使用Hybrid,只要想办法让代码去触发onSurfaceCreated就行。

@marchlqq
Copy link
Author

marchlqq commented Dec 4, 2024

嗯,暂时看是的。最好的办法,还是flutter,去修复这个问题,或者看看在什么合适的时机,改变 isPaused 状态。就跟之前手动处理的 platformview 的显示和隐藏一样。

@joechan-cq
Copy link
Collaborator

这个应该很难让Flutter去修改了,因为纯Flutter不存在跨Activity切换Surface的情况。真要FlutterBoost解决这个问题,之前为了修复 #1960 的PR里的动态代理的方案改改应该是能用的。

@marchlqq
Copy link
Author

这个应该很难让Flutter去修改了,因为纯Flutter不存在跨Activity切换Surface的情况。真要FlutterBoost解决这个问题,之前为了修复 #1960 的PR里的动态代理的方案改改应该是能用的。

最近苹果升级到 18.2 版本,必须得升级到 3.27.1,然后这个修改,又无效化了。

image

设置了
SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false);
反而显示白屏了。
不设置,又还是之前的问题。可能底层又改了 surface 的状态。

@marchlqq
Copy link
Author

查了一下,是 FlutterMutatorView 变成了 gone,不知道哪里出了问题,还得查查。
image

@marchlqq
Copy link
Author

这里增加了 initializePlatformViewIfNeeded(viewId),导致 return 了。
public void onDisplayPlatformView( int viewId, int x, int y, int width, int height, int viewWidth, int viewHeight, @NonNull FlutterMutatorsStack mutatorsStack) { initializeRootImageViewIfNeeded(); if (!initializePlatformViewIfNeeded(viewId)) { return; }

导致,后面的 contains 为false,然后platformView就没有显示。
if (currentFrameUsedPlatformViewIds.contains(viewId) && (isFrameRenderedUsingImageReaders || !synchronizeToNativeViewHierarchy)) { parentView.setVisibility(View.VISIBLE); } else { parentView.setVisibility(View.GONE); }

@marchlqq
Copy link
Author

我去flutter里面也增加了提问,看看那边有什么解释。
flutter/flutter#160490

@marchlqq
Copy link
Author

我调试运行后,方法 onBeginFrame,在运行几次以后,后面不会运行 onDisplayOverlaySurface,
3.24.5:
onBeginFrame -> onDisplayPlatformView -> onEndFrame

3.27.1:
开始运行:
onBeginFrame -> onDisplayPlatformView -> onEndFrame

运行几次以后:
onBeginFrame -> onEndFrame

暂时不清楚原因。

我看跟方法改动:

    initializeRootImageViewIfNeeded();
    if (!initializePlatformViewIfNeeded(viewId)) {
      return;
    }

关系不大。

@joechan-cq
Copy link
Collaborator

我这边在flutter boost的example中的webview_flutter_demo.dart里的weview的实现改成InAppWebView,并没有出现你说的问题。

@marchlqq
Copy link
Author

需要增加代码:

SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false);

最后我的回复,我下午尝试复现了:flutter/flutter#160490

@marchlqq
Copy link
Author

@joechan-cq
有复现没?你改成 InAppWebView,需要运行一下
SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false);
是必现的,我继承 PlatformViewsController,在方法 onEndFrame,强制可见,也不行。

@marchlqq
Copy link
Author

@joechan-cq
还是使用 FlutterImageView 的话,可以处理吗?
就是这段代码不加,
SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false);
我发现是flutter 那边的engine c++代码修改,造成的这个问题,暂时不清楚该如何解决。他们目前也没有回复。
flutter/flutter#160490

@joechan-cq
Copy link
Collaborator

@joechan-cq 有复现没?你改成 InAppWebView,需要运行一下 SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false); 是必现的,我继承 PlatformViewsController,在方法 onEndFrame,强制可见,也不行。

我用inAppWebView的项目,加synchronizeToNativeViewHierarchy代码也没有复现。

@joechan-cq
Copy link
Collaborator

@joechan-cq 还是使用 FlutterImageView 的话,可以处理吗? 就是这段代码不加, SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false); 我发现是flutter 那边的engine c++代码修改,造成的这个问题,暂时不清楚该如何解决。他们目前也没有回复。 flutter/flutter#160490

如你之前所说,修改isPaused的值应该就行了

@marchlqq
Copy link
Author

@joechan-cq 有复现没?你改成 InAppWebView,需要运行一下 SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false); 是必现的,我继承 PlatformViewsController,在方法 onEndFrame,强制可见,也不行。

我用inAppWebView的项目,加synchronizeToNativeViewHierarchy代码也没有复现。

需要用3.27.1的flutter版本。

修改isPaused,我晚点试试。

@joechan-cq
Copy link
Collaborator

joechan-cq commented Dec 24, 2024

@joechan-cq 有复现没?你改成 InAppWebView,需要运行一下 SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false); 是必现的,我继承 PlatformViewsController,在方法 onEndFrame,强制可见,也不行。

我用inAppWebView的项目,加synchronizeToNativeViewHierarchy代码也没有复现。

需要用3.27.1的flutter版本。

修改isPaused,我晚点试试。

是的, 我用的就是3.27.1的Flutter。这么看,可能和设备也有关系

@joechan-cq
Copy link
Collaborator

看engine那边的提交记录,确实和设备GPU型号有关,另外不用Impeller估计也没这个问题。

@marchlqq
Copy link
Author

我这边验证了小米+oppo,一共4台设置,都是必白屏。也可能这几台设备都差不多吧。

@marchlqq
Copy link
Author

@joechan-cq 还是使用 FlutterImageView 的话,可以处理吗? 就是这段代码不加, SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false); 我发现是flutter 那边的engine c++代码修改,造成的这个问题,暂时不清楚该如何解决。他们目前也没有回复。 flutter/flutter#160490

如你之前所说,修改isPaused的值应该就行了

我验证了,单独反射调用,时机上不好弄,在 FlutterEngineAttachmentListener 里面调用,反射不行,找到 flutterView的方法,revertImageView 里面有调用 resume,使用以后,是可行的。

// 解决HybridComposition PlatformView中间页面问题
flutterView.addFlutterEngineAttachmentListener(new FlutterView.FlutterEngineAttachmentListener() {
    @Override
    public void onFlutterEngineAttachedToFlutterView(@NonNull FlutterEngine engine) {
        FlutterBoostFixUtil.log(FlutterBoostFixUtil.TAG, "onFlutterEngineAttachedToFlutterView: ");
        // 显示之前的记录的platform view
        showPlatformViews(true);
        if (flutterView != null) {
            flutterView.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onFlutterEngineDetachedFromFlutterView() {
        FlutterBoostFixUtil.log(FlutterBoostFixUtil.TAG, "onFlutterEngineDetachedFromFlutterView: ");
        // 解决platformView 切换的时候,显示异常的问题
        // 这里根据url 记录platform view,隐藏view
        FlutterBoostFixUtil.findFlutterPlatformViews(FlutterBoostActivity.this, platformViews,getFlutterEngine(), getUrl());
        if (flutterView != null) {
            // 解决flutter 从3.16.9,升级到3.24.x,flutter platformView 显示异常的问题
            // platformView 的状态存在问题,flutter 升级以后,renderSurface 调用了 pause 改变了状态,需要调用 resume 改变回去
            // 1、单独调用 resume 没有效果;2、使用 SystemChannels.platform_views.invokeMethod('synchronizeToNativeViewHierarchy', false); 存在 3.27.0,升级到3.27.1,flutter 白屏的问题
            // # https://github.com/alibaba/flutter_boost/issues/2161
            flutterView.revertImageView(new Runnable() {
                @Override
                public void run() {

                }
            });
            flutterView.setVisibility(View.INVISIBLE);
        }
        showPlatformViews(false);
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants