從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的實現問題,懸空指針沒有解決,這些都會形成野指針訪問內存的崩潰。