iOS集成flutter混編內(nèi)存泄漏問(wèn)題

如果不知道如何集成flutter可以看我的上一篇文章《iOS老項(xiàng)目集成flutter最新混編方案》

集成flutter進(jìn)入項(xiàng)目后發(fā)現(xiàn)每次進(jìn)入flutter模塊都是導(dǎo)致內(nèi)存增加60M-80M并且退出flutter頁(yè)面后,內(nèi)存并不會(huì)釋放,具體原因是由于每次進(jìn)入Flutter頁(yè)面都會(huì)創(chuàng)建新的的FlutterViewController,但退出的時(shí)候并沒(méi)有釋放。

為什么google難以解決:

由于整個(gè)FlutterEngine是用MRC的方式編寫(xiě),所以內(nèi)存管理比較困難,每個(gè)變量生成retain,都需要被release,如果一個(gè)實(shí)例retain了兩次,只release一次,也會(huì)導(dǎo)致無(wú)法釋放,如果設(shè)置了autorelease,就有可能提前釋放,導(dǎo)致badasses,訪問(wèn)野指針。

客觀原因,一般的應(yīng)用只會(huì)創(chuàng)建一個(gè)flutter應(yīng)用,或者干脆就直接都是flutter應(yīng)用,不釋放就不釋放,多點(diǎn)內(nèi)存也無(wú)所謂,不影響崩潰,不影響使用,所以google照常發(fā)布1.0版。

官方發(fā)布最新的解決方案,使用FlutterEngine初始化FlutterViewController

FlutterViewController *flutterViewController = [[FlutterViewControlleralloc]initWithEngine:flutterEnginenibName:nilbundle:nil];

通過(guò)類(lèi)別發(fā)現(xiàn),此方案確實(shí)使FlutterViewController釋放,但拒網(wǎng)上查詢資料得知google團(tuán)隊(duì)只是將內(nèi)存泄漏轉(zhuǎn)嫁到FlutterEngine對(duì)象上,并沒(méi)有徹底解決內(nèi)存問(wèn)題,實(shí)踐發(fā)現(xiàn),每次打開(kāi)Flutter頁(yè)面內(nèi)存會(huì)增長(zhǎng)不到1M左右,與之前暴漲的80M內(nèi)存相比,此方案還是在可接受范圍。

有大神徹底解決內(nèi)存泄漏的問(wèn)題,通過(guò)自己修改frameword的方式,有興趣的可以了解下相關(guān)文章。傳送門(mén)

但是這個(gè)方案有個(gè)致命的缺陷,就是每次flutter升級(jí)都需要下載最新的frameword文件,對(duì)于沒(méi)有能力自己編寫(xiě)frameword文件的同學(xué),我更加傾向于官方的解決方案,不到1M的內(nèi)存泄漏還是在可以接受的范圍內(nèi)的。

官方方案:


AppDelegate.h


AppDelegate.m


ViewController.m

但是,使用官方解決方案發(fā)現(xiàn)我們想通過(guò)[flutterViewControllersetInitialRoute:@"route1"];通過(guò)不同的routename加載不同flutter頁(yè)面不再生效,原因是在AppDelegate中運(yùn)行[self.flutterEnginerunWithEntrypoint:nil];這行代碼的時(shí)候,flutter已經(jīng)初始化好了,這時(shí)在flutter中通過(guò)window.defaultRouteName獲取到的route一直是默認(rèn)的/,為了解決可以加載不同flutter頁(yè)面的問(wèn)題,我通過(guò)native向flutter發(fā)送消息,flutter接受到消息后加載不同頁(yè)面的方法來(lái)解決。


flutter代碼
flutter代碼


oc代碼
oc代碼

這時(shí)問(wèn)題又來(lái)了,flutter中調(diào)用eventChannel.receiveBroadcastStream(postArg).listen(onData ,onError: onError);時(shí),OC代碼中的FlutterEventChannel還未運(yùn)行到,這就導(dǎo)致eventSink綁定不成功,所以[flutterEngine runWithEntrypoint:nil];與FlutterEventChannel對(duì)象必須同時(shí)生成,我是通過(guò)單例解決這一問(wèn)題的:


單例.h


單例.m

項(xiàng)目啟動(dòng)初始化單例,如果等到點(diǎn)擊進(jìn)入flutter頁(yè)面的時(shí)候再初始化單例,這時(shí)[flutterEngine runWithEntrypoint:nil];運(yùn)行,flutter剛剛創(chuàng)建會(huì)導(dǎo)致跳轉(zhuǎn)時(shí)頁(yè)面會(huì)白2-3秒,所以在項(xiàng)目初始化時(shí),將flutter也初始化。

初始化單例

代碼Demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容