从Flutter technical-overview基本架构来讲framework是使用最频繁的,可是对于engine和embedder确是flutter的底层,支持整个flutter的运行android
flutter 有三个学习层次,framework,engine,embedder 上层的framework负责ui相关的事情,动画,widget,绘图,手势,基础库 engine层次c++实现,支持flutter相关的渲染,线程管理,平台事件。ios
engine里面有个内存泄漏,flutter官方一直没有解决,能够出门左转找到解决方案《手把手教你解决flutter内存泄漏》。一句话就是,flutter在处理flutter method channel和register与engine之间持有关系比较混乱,存在一个比较大的循环引用。c++
embedder 为engine提供四个task runner,将引擎移植到平台的中间层代码 渲染设置,原生插件,打包,线程管理,事件循环交互操做git
在shell.cc里面能够看到,四个runner包括 ui runner gpu runner、io runner、platform runnergithub
ui runner负责绑定渲染相关的操做,如通知engine有帧渲染,等待下一个vsync,对建立的widget进行layout并生成layer tree,更新layer tree信息,通知处理native plugin信息,如timer,microtask,异步io操做shell
gpu runner是用于执行gpu指令,负责将layer tree提供的信息转换为平台可执行的gpu指令,负责绘制gpu资源的管理,包括framebuffer,surface、texture、buffersbash
io runner是处理图片数据,为gpu渲染作准备,好比读取磁盘压缩图片的格式,将解压成gpu能处理的格式,并传给gpu,因其比较消耗性能因此单独开一个线程。数据结构
platform runner,全部接口调用都使用该接口,长时间卡顿将会被watchdog强杀。架构
runner的实现策略,ios、android平台启动时为ui,gpu,io runner各自建立一个线程,可是共享platform runner和线程 Fushia,为ui,gpu,io,platform各自建立一个线程。并发
isolate 是dart vm本身管理,engine没法访问,它是对actor并发模式的实现,运行中程序由一个或多个actor组成,这些actor就是isolate。
原意是隔离的意思,表示没有共享内存和并发,逻辑上隔离,按顺序执行,不用担忧死锁的问题。 isolate直接的通讯方式只能经过port,消息传递异步,与普通线程最大的区别就是没有共享内存。 实现的步骤有,初始化isolate数据结构,初始化堆内存,进入对应所在的线程运行isolate,配置port,配置消息处理机制,配置debugger,将isolate注册到全局监控器。
与runner的关系,isolate是dart vm本身管理,engine没法访问。 如对于ui runner来讲,isolate经过dart的c++调用能力,将ui渲染任务提交到ui runner,这样能够跟engine相关模块进行交互,ui相关的任务被提交到ui runner也给isolate一些事件通知,因此isolate同时处理app和native plugin的任务 对于gpu rnnner来讲,isloate将dart的c++调用能力把gpu指令提交给gpu runner,把layer tree信息转换为gpu指令,这些都是经过isolate来执行的
分享一个坑,emmberdder里面有一个fml weakptr会形成四个task runner在reset的时候释放,可是不会把指针置空,会在必定概率下关闭flutterviewcontroller,形成崩溃,由于访问了野指针,fml的实现使用了uniqueptr智能指针,若是控制很差,这个应该后期会给flutter带来比较大的崩溃率。
测试代码
-(void)handleAutoRelase{
FlutterBasicMessageChannel* channel;
FlutterEngine * engine;
@autoreleasepool {
FlutterViewController* flutterViewController =
[[FlutterViewController alloc] init];
channel = flutterViewController.engine.systemChannel;
engine = flutterViewController.engine;
NSLog(@"engine111:%@",engine);
}
NSLog(@"engine222:%@",engine);
[channel sendMessage:@"Hello!"];
[channel setMessageHandler:^(id _Nullable message, FlutterReply _Nonnull callback) { }];
}
复制代码
以上代码是google工程师提供的测试代码,autoreleasepool中包括了flutter和engine的建立,而后自动释放,而后在释放以后从新调用sendmessage的方法,此时会有一个访问野指针的崩溃。 对于engine的改写就须要在释放的时候防止对内部方法的访问
这样能够防止释放时候崩溃,可是对于根本的缘由是fml内部实现的问题,如上所说,释放完成而指针变成了悬空指针。
engine的第二个隐患,在shell.cc访问weakptr必定会获得一个不为空的指针,即便是在engine或platformview释放的时候,如下是它的实现代码
粗略算了一下,四个taskrunner的getweakptr方法的实现都有隐患,归根到底仍是fml的实现问题,悬空指针没有解决,这些都会形成野指针访问内存的崩溃。