Flutter_boost混编开发系统MethodChannel之坑
一、背景
Android、iOS原生项目集成Flutter混合开发,常见的接入方式flutter_boost管理维护路由栈,flutter引擎采用单引擎复用,新开发的Flutter页面采用Android原生Actvity路由栈管理,启动一个统一命名的FlutterBoostActvityImpl的接入actvity。
二、主体设计
flutetr_boost + 单引擎复用 + 单命名FlutterBoostActvityImpl ---- 这种模式。
说明:这个单命名FlutterBoostActvityImpl 表示定义了一个统一的接入Actvity类,但是启动模式默认标准,如果有多个flutter业务界面,可以启动多个相同该类名的对象。
三、认识PlatformChannel
这个业务类是Flutter封装的平台通信,用来和平台建立通道,请求设置系统的音效、状态栏、虚拟导航、剪切板等操作。
该业务类的创建时机:
FlutterBoost.instance().setup()
即flutter引擎创建初始化(基于Flutter_boost)。
该类成员对象:
唯一的一个函数通过channel、内部成员对象 parsingMethodCallHandler、平台消息Handler对象platformMessagehandler,parsingMethodCallHandler 用来接受channel机制的函数调用,而parsingMethodCallHandler的函数调用根据不同case调用platformMessagehandler的不同实现。
问题: platformMessagehandler 对象什么设置的?
答案:Actvity创建、销毁两个时机。这就存在一个问题,如果关闭一个Flutter的Actvity再打开Flutter的Actvity,就可能因为onDestory的生命周期不确定性,致使最后打开的Flutter的Actvity操作所设置的该handler对象被替换污染,这个污染会时Fluuter业务代码操作该channel无效。
四、认识PlatformPlugin
这个业务类时平台插件,类关系:
构造函数入参:Activity、platformChannel、插件代理对象delegate等。
构造函数会设置channel的handler对象,这个对象 mPlatformMessagehandler就是传递给上述二中的PlatformChannel.PlatformMessageHandler对象。该对象是PlatformPlugin的一个内部成员对象,最终对channel机制的函数调用就执行到这里,调用了 PlatformPlugin 的业务实现(持有一个Actvity实例)。
构造函数执行时机:Actvity启动创建时机
上述红色框为例:
public void showSystemUiMode(@NonNull PlatformChannel.SystemUiMode mode) {
setSystemChromeEnabledSystemUIMode(mode);
}
该函数是Flutter侧通过SystemChrome设置状态栏模式。
到这里基本清楚了Flutter的业务调用。
五、理解系统PlatformChannel之坑
看了上述到简单分析,如果需要在Flutter界面采用类似如下:
void initState() {
super.initState();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
}
用来设置系统状态栏模式沉浸模式。你可能会猜到了存在多个Actvity示例场景会发生状态栏模式设置概率失效的问题。
当然这个问题在纯Flutter开发单Actvity模式下是不存在的,发生在混合开发多Actvity场景。
怎么解决问题呢?
想到的方式是不使用原生的设置方式,自己建立一个MethodChannel,Actvity侧注册channel,建立通信调用原生设置。如果要和Actvity对象绑定,可以创建唯一性id传递给Flutter,并由Flutter调用回传给Actvity以实现唯一性对应匹配。