起因
隨著專案不斷的迭代,功能日益復雜,記憶體占用也與日俱增,在壓測程序中,app的崩潰也多是因為各種原因的記憶體泄漏或例外抖動并最終引發OOM而被系統殺死,按技術堆疊劃分主要集中以下兩端:
-
原生端本身的代碼質量(不當設計、圖片加載、物件未釋放等)所造成,這點通過回溯及找到組內對應同學修復便可快速解決,
-
前端的代碼質量(亦如上)所引起,這點則需要找到前端組的同學進行修復,但是跨組/部門的無力感我想大家或多或少都會有一些,
不管原因幾何,結果都是App崩了,我們一方面找到負責的同學抓緊修復外,另一方面也在思考如何從原生解決(至少隔絕)H5導致的App崩潰問題,
分析
有一定原生開發經驗的我們,便想到了子行程,而通過子行程去分擔主行程的記憶體壓力,在各大廠也均有應用,可證明它是一個比較成熟的方案,而就單行程Web-View來說,市面上也有不少成功的Android框架及技術方案的分享,
就純原生(Android)應用來講,因為堆疊的統一,接入一個子行程web-view,還是比較方便的,大致開啟一個子行程,然后startActivity即可,無需關心堆疊的管理,但是Flutter應用則分為兩種堆疊:
1 Android堆疊 (管理activity)
2 Flutter堆疊 (管理flutter的route)
在實際應用中,H5與原生均有復雜的互動,這里不僅體現在功能上的,還包括UI上的,就算不考慮跳轉影片的問題,Flutter堆疊內的疊加(Flutter和H5)就需要一個單獨的堆疊管理器來處理(如Flutter Boost),
在考慮到投入產出成本以及問題的本質并非堆疊管理器可以解決的情況下(如 Flutter頁面部分是H5等情況),我決定用Flutter自帶的Texture Widget進行H5的顯示,這樣統一了堆疊的管理,同時Texture Widget可以自由調整大小,做到任意Flutter頁面的(部分)嵌入,Texture Widget需要一個Surface,而Surface又具有天然的跨行程屬性這無疑大大方便了開發,
實踐及結果
經過一段時間的研究和設計,最終有了一個Alpha版的框架,在此我對架構做一下簡單的介紹:

按行程劃分
主要分為兩部分:
1\. 主行程包含Flutter及相應的平臺部分,承擔surface的創建、展示、互動等的發起方,
2\. 子行程主要包含zygote activity , webview 等,
復制代碼
行程之間通過Binder進行通信,
按流程劃分
主要分為三部分:
1\. Flutter側,主要發起創建指令并最終消費子行程的渲染資料,
2\. 平臺側,主要承擔Flutter與子行程的web-view的通信轉發功能,同時承擔surface的創建功能,
也是真正與子行程通信的模塊,
3\. 子行程,主要負責webview的創建,并使用主行程所提供的surface進行H5內容的輸出,
所遇到的一些難點
系統彈窗的權限問題
在子行程中使用web-view,并渲染在指定surface 上需要借助virtual display 和 presentation,但是如果presentation的創建不是基于activity 的context,那么則需要一個系統權限才可以正常作業,這對于我們的需求來說,是不可接受的,
為此便創建了一個Zygote activity,它作業于后臺,主要責任就是提供一個context和部分presentation的創建作業,同時借助記憶體泄漏以盡可能長的保留它的存活時間,
互動
由于系統事件(如 觸摸)是分發到當前(前臺)activity stack的堆疊頂activity,那么當Zygote activity作業于后臺的時候,我們的觸摸事件是分發到了Main activity,h5則無法回應任何互動,因此我們需要在主行程做事件的分揀并通過binder轉發到子行程,以此來讓H5消費到屬于它的事件,
觸摸事件的分發及錯位問題
上面的問題細分后,可以明確我們需要解決Flutter端的H5頁面在非堆疊頂的情況下不能消費事件,因為Flutter所接受的事件由Main Activity提供,所以事件的分發也在此處處理,為此我增加了一個堆疊協調器(相對于堆疊管理要簡單一些),以獲取當前Flutter端的堆疊情況,并做出正確的分發,
經過實際實踐,效果還是不錯的,但也發現一個問題:點擊坐標錯位,經過研究發現,這主要是Flutter端布局和web view端布局不一致導致的,換言之需要計算在Flutter點擊時的position相對于那個Texture widget內的相對位置,并做轉換再進行分發,
通信
客觀的說,這里并沒有什么難點,但比較繞,因為操作涉及到UI,所以不僅要考慮到行程間的通信、執行緒切換還有各行程的主、子執行緒的切換,并且按領域進行劃分話,又分為共有和私有通信,為此增加了communicate hub以區分各領域的通信,
結果
在一些主要問題解決后,得到了最終的效果圖(debug mode):

這個Demo并不滿足生產,但是驗證了它的可行性,而就真正的上線來說,還是有一部分作業要做的,如坐標轉換器優化(下一個版本要做的)、協調器、垃圾回收、兜底策略等等,
更多Android知識點在下方小卡片中
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/303082.html
標籤:其他
下一篇:uniapp申請ios證書
