ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

flutter_hybird_webview 跨进程渲染的实践技术分享

2021-12-27 12:31:41  阅读:202  来源: 互联网

标签:event 插件 hybird app Flutter 进程 webview flutter



theme: channing-cyan

前言

大家好,继 Flutter跨进程混合栈渲染的实践——子进程WebView 之后,利用业余时间对整个插件进行了完善和基础测试,诚然距离投入生产还有一段距离,但总算能达到beta阶段了(仓库地址在文尾)。

这个插件断断续续开发了有小半年,最初只是为了隔离webview,但随着不断地实践,发现在app容器化小程序等方面也可能有不错的应用和表现。故,在此做一个记录和分享,希望能帮到有需要的朋友,同时对于不足的地方,也望大佬能给予指点。

限于篇幅,此文仅对插件做一个整体性的介绍,后续会对具体的子模块做详细介绍。

介绍

目前仅支持android端,以下也基于Android平台进行介绍

flutter_hybird_webview旨在将webview隔离到子进程以避免其对主进程的影响,同时为了不增加栈的管理复杂度,采取子进程渲染,主进程显示的方式来保持flutter栈的唯一性。

演示(多图)

gif已转为webp。总计约10m+

1.webp

2.webp

3.webp

4.webp

技术原理

组织架构图

老版架构图,结构一致,细节略有变动。

alt

原理介绍

下面对插件的主要模块进行介绍

渲染模块

flutter端采用的是texture widget,其特点是可以配合平台端的surface进行显示。

当我们在flutter侧通过widget构建一个页面时,最终会在engine侧形成一个layer treeskia会通过里面录制的绘制指令,绘制(skia底层绘制方式还是由平台来决定的,如opengl,vulkan,metal等)到surface所指向的内存缓冲区。

layer.png

rasterizer runner为engine在app进程开启的一条线程,主要负责绘制相关。
还有诸如:platform、io、ui等Runner.

如果了解绘制原理,应该知道surface是由平台侧提供的,而平台侧的surface对应Surface Flinger服务进程的layer(一一对应关系),其内部含有一个BufferQueue可以根据需要来申请一块内存缓冲区并通过映射共享给其他进程(如app)。简单讲,surface内部包含一个指针并指向了一块内存区域,我们绘制的数据最终会在那个内存区域里。

这里不做过多介绍,有兴趣的可以百度

由上面我们可以知道surface是具有跨进程能力的,那么我们便可以通过在主进程创建surface然后共享到子进程(甚至可以反过来),并由其来提供绘制指令。

cp-layer.jpg

通过上述方式便确保了栈的唯一性,降低了管理栈所带来的额外成本。

Touch event模块

    Touch event由硬件传感器生成并最终传递到app,Input event则由输入进程(包括那个软键盘窗口)
    产生并传递到app,也就是说这些event 天然具备跨进程传递。

Flutter的触摸事件是由平台侧传递过来,并进行分发的,可参考Flutter——原生View的Touch事件分发流程 以及更早的文章。

起初我是打算在平台侧做拦截并进行分发的,但考虑到view在具体使用时的环境可能非常复杂,如 部分显示表面有浮层可见但无法消费事件等等,所以放弃了这个方案,并参考google的实现,改由在flutter侧处理并回传到平台层,再分发到子进程。

touch.jpg

这里之所以增加event coordinator 模块,是因为view在具体显示的时候并非充满整个页面,需要将点击坐标转换成相对坐标分发到子进程的remote view

Input event模块

由于软键盘的拉起,需要view获得focus以及display id的匹配,官方的trick并不能解决在多进程下无法拉起软键盘的问题。

经过思考得出两个方案:

方案一

通过对源码的分析,可以知道app是通过binderIMS通信来实现输入功能的,那么我们对IMS的binder : IInputMethodManager进行代理以监听软键盘的show请求,然后通过app的binder通知主进程代劳,并将input event分发到子进程,便可以完成这个功能。

一通理论分析后,便信心满满的开干,结果被现实打得鼻青脸肿…Android较新的版本,不仅binder有缓存,就连imm也增加了缓存,而且由于高版本的api限制导致无法正常hook。在通过进一步研究和大佬的指点,发现可以通过native层的hook或者匿名调用来绕过限制。

由于工程量较大,所以插件的实现暂未采用方案一,而是临时采取方案二

方案二

在仔细分析了android和chromium的input模块的通信流程和源码后,采用了通过对getSystemService方法重写,然后对调用堆栈进行分析,来判断webview是否请求了软键盘的弹出操作。

具体运行效果尚可,但个人的目标还是方案一,后续将会抓紧时间来实现此方案。

通信模块

整个插件按照通信端来划分,可以分为3部分:

flutter端
平台端
子进程端

comm-framework.jpg

插件的管理及widget/view的内部通信都是基于这个通信架构来设计开发的,通信实现由channelbinder配合完成。为了降低通信管道的复杂度,对通道进行了属性上的划分:管理通道私有通道

管理通道: 负责整个插件的生命周期管理及维护命令的分发。
私有通道:view内部的私有通道,处理定制化命令的分发。

具体通信流程如下图:

comm.jpg

后语

至此整个插件的基本介绍就到此结束了,由于一些子模块涉及的东西较多,所以会在后续文章中做详细介绍,谢谢大家阅读,如有错误还望指出。

仓库地址

暂时不能用于生产哦~ 具体分支含义见仓库的readme。

flutter_hybird_webview

其他文章

Flutter——原生View的Touch事件分发流程

Flutter在Android平台上启动时,Native层做了什么?

Flutter版 仿.知乎列表的视差效果

Flutter——实现网易云音乐的渐进式卡片切换

Flutter 仿同花顺自选股列表

标签:event,插件,hybird,app,Flutter,进程,webview,flutter
来源: https://blog.csdn.net/ljq5945/article/details/122169283

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有