tags: flutter
engine
memory
leak
fix
natoto
ios
0809 flutter engine開發qq羣 217429001git
0708 官方engine 有個 destorycontext能夠釋放內存,可是會偶發崩潰github
0305 更新flutter 1.2內存引用問題數據庫
demo地址bash
團隊在0.9.4 版本解決了一系列循環引用,可是代碼不能上傳,因爲flutter和engine的限制,必須flutter版本號和engine的commit號要保持一致,提交了將致使commit號不一致的問題,致使運行失敗,官方號稱1.0解決了循環引用,下載了一看,使人失望,仍是沒有完全解決,因而決定
本身動手,豐衣足食
,通過了幾天痛苦的下載編譯,調試,測試,終於把內存降下來了。架構
歡迎關注 姊妹篇《手把手教你編譯Flutter engine》app
google團隊的大bug,我的認爲內存是很重要的,尤爲是集成到現有app中的方式。ide
github.com/flutter/flu… github.com/flutter/flu… github.com/flutter/flu… github.com/flutter/eng… github.com/flutter/flu…post
flutter 1.0 解決了FlutterViewController的循環引用問題,可是把循環引用的問題轉嫁到了FlutterEngine上面,下面手把手教你如何解決1.0的循環引用。測試
因爲整個FlutterEngine是用MRC的方式編寫,因此內存管理比較困難,每一個變量生成retain,都須要被release,若是一個實例retain了兩次,只release一次,也會致使沒法釋放,若是設置了autorelease,就有可能提早釋放,致使badasses,訪問野指針。
客觀緣由,通常的應用只會建立一個flutter應用,或者乾脆就直接都是flutter應用,不釋放就不釋放,多點內存也無所謂,不影響崩潰,不影響使用,因此google照常發佈1.0版。
每次進去都會新增幾十M然而當退出flutterViewController的時候,內存僅僅降低2m左右,還有幾十兆保留在內存中。降低的部分就是flutterviewcontroller,從程序運行到了dealloc能夠證實。
修改後的framework下載列表
1.0版engine arm64 debug下載 github.com/Natoto/flut…
其餘版本打包發佈github 地址 github.com/Natoto/fixF…
下面將一步步帶領你們找到循環引用,解決循環引用,這一步可能比較繁瑣,若是不肯看推理過程,能夠直接跳到文末獲取構建後的framework。
/**
* 加載boundle資源
*/
- (void)handleBoundleResource {
NSString * path = [[NSBundle mainBundle] pathForResource:@"flutter_assets" ofType:@""];
NSURL * url = [NSURL URLWithString:path];
FlutterDartProject * dart = [[FlutterDartProject alloc] init];
if (!self.engine) {
FlutterEngine * engine = [[FlutterEngine alloc] initWithName:path.lastPathComponent project:dart];
[engine runWithEntrypoint:nil];
self.engine = engine;
}
FlutterViewController* flutterViewController = [[FlutterViewController alloc] initWithEngine:self.engine nibName:nil bundle:nil];
[GeneratedPluginRegistrant registerWithRegistry:flutterViewController];
[self addBackButton:flutterViewController];
[flutterViewController setInitialRoute:@"route1"];
[self presentViewController:flutterViewController animated:YES completion:nil];
}
複製代碼
flutterEngine
, flutter官方推薦方式是本身管理flutterEngine,而後flutterviewcontroller是能夠獨自建立和釋放,FlutterEngine
是新1.0引進,用於管理全部的metchodChannel,就是維護全部的方法消息,生命週期等做用。也是要解決它的引用問題。 執行engine runwithEntrypoint
能夠啓動engine vm。
FlutterDartProject
用於配置啓動參數,默承認以直接new,或者從bundle啓動,找boundle下面的的flutter_assets文件夾,或直接導入App.framework
FlutterViewController
用來顯示flutter工程的,全部的界面都是在其上面渲染出來的。跟普通的UIViewController同樣,能夠present出來,或者push出來。
plugin是flutter的入口,這個入口能夠鏈接flutter和原生代碼 好比自帶的GeneratedPluginRegistrant
,將flutter工程中用到的插件都集中註冊到原生
@implementation GeneratedPluginRegistrant
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[FlutterWebviewPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterWebviewPlugin"]];
[FLTPathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTPathProviderPlugin"]];
[FLTSharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTSharedPreferencesPlugin"]];
}
@end
複製代碼
介紹上面兩個是爲了找到斷點入口
爲了方便調試,能夠在編譯現有工程的時候替換flutter.framework 具體作法是在build phases 中建立一個腳本,用本身編譯的engine中的flutter.framework替換 .ios/engine/Flutter.framework
替換完以後則能夠設置symbol斷點了,以下
或者用lldb命令設置斷點 br xxxx
lldb傳送門
從目前的狀況來看engine沒有被釋放,就是FlutterEngine.mm
FlutterChannel.mm
和 PluginRegister
直接的關係混亂了 有兩點狀況
方法論說完了,下面直接說個人幾天試錯結果。共計10個文件,核心的地方貼一下
maybesetupPlatformViewChannels
在flutterengine裏面,啓動默認平臺changnle和方法回調
重心,FlutterChannel.mm裏面 FlutterMethodChannel
,flutter每一個plugin的方法都會通過經過register註冊一個channel,然而,messger是register,不該該被持有或autorelease的,因此這樣作是會形成提早釋放或沒法釋放的
對應於其餘的channel也是用了messager,會有相同的問題。改造這些基本上就能解除大循環了。
有兩種方法
替換flutter裏面的framework 路徑以下 /Users/boo/Documents/flutter/bin/cache/artifacts/engine/ios
不用擔憂是否會破壞以前發flutter.framework,若是想用回官方的直接解壓同文件夾裏面的.zip文件便可
工程中用zip,解壓成framework替換掉真正從官方複製過來的flutter.framework 適用於 arm64真機
工程配置添加sh腳本
#R.replace.engine
cd "${SRCROOT}/flutterOnExistApp/Resources/"
unzip -u Flutter.framework.zip
cp -rf "${SRCROOT}/flutterOnExistApp/Resources/Flutter.framework" "${SRCROOT}/myflutter/.ios/Flutter/engine"
複製代碼
修改的文件放在1.0engine修改的文件
,能夠直接替換使用並構建本身的framework
1.0 修改的代碼地址 github.com/Natoto/flut…
github demo 工程 github.com/Natoto/flut…
1.0版engine arm64 debug下載 github.com/Natoto/flut…
看一下構建後結果
如構建debug版的engine以下路徑或生產一個framework,這個經過執行all.wxworkspace
生成的,注意arm架構,若是選target是真機,則會生成arm64架構framework /Users/boo/Documents/engine/src/out/ios_debug/Flutter.framework
這個能夠直接替換掉工程中原有的framework
構建release framework相似。 詳細步驟能夠參考《手把手教你編譯Flutter engine》
一行代碼教你解決FlutterPlatformViews內存泄露 by AShawn
手把手教你在Flutter項目優雅的使用ORM數據庫 by williamwen1986
flutter通用基礎庫flutter_luakit_plugin by williamwen1986
github - flutter_luakit_plugin使用例子 by williamwen1986
手把手教你解決 Flutter engine 內存泄漏 by 共田君
github - 編譯產物下載 修復內存泄漏後的flutter engine(可直接使用)by 共田君
github demo - 修復內存泄漏後的flutter engine by 共田君
持續更新中...