Fragment的原理和優化

2021-08-24 18:08:18 字數 1993 閱讀 3328

fragment 管理框架公升級到了 0.1.0, 新增了乙個新的介面startfragmentanddestroycurrent, 可以方便的完成類似startactivity之後 finish 的效果

之前也有人在 issue 中問道如何實現類似activity#finish()的效果,我不加思索的回答到:

fragmenttransition有提供addtobackstack(boolean)方法, 啟動前乙個 fragment (不是新的那個)時,addtobackstack傳參為 false 就行。

這樣初看也確實解決了問題,一切看似完美,直到另乙個 issue 的出現。在閱讀原始碼來解決這個問題時,我發現了addtobackstack(false)是存在問題的,這篇文章會指出問題所在,然後給出 qmui 的解決方案。

在之前的文章我也有提到, backstack 並不是將 fragment 儲存到堆疊,而是將操作(add, remove等)儲存到堆疊,然後在返回時將操作逆著來就行。

在開始之前,先介紹 fragment 的乙個私有成員變數:

fragment存在乙個成員變數mbackstacknesting,它是標誌 fragment 是否存在於 backstack 的重要變數,每個 fragment 的每次操作都會影響到它, 只有它的值小於等於0時,fragment 才會走到 ondestroy,從而得到釋放

一般情況下,我們切換 fragment 時 backstack 的變更行為為:

現在,讓我們來看看使用addtobackstack(false)時會發生什麼:

回到之前提到的 issue。其出錯的原因是findcurrentfragment出錯,而findcurrentfragment會先在被新增到 fragmentmanager 中的 fragment 佇列中去尋找,根據上面的描述,addtobackstack(false)會導致頁面存在多個 fragment, 所以猜測可能是它導致的問題,但我也不能確定我的猜測 100% 正確,因為我並沒能在開發環境中重現。

現在來說說 qmui 的 fix 方案。其實也很簡單,我們直接對 backstack 的最後乙個 entity 做一些修正(以上圖為例):

修改 op[addb] 替換為 op[addc]

將 b.mbackstacknesting 賦值給 c,完成 backstack 中對 b 的替換

b.mbackstacknesting減一 或者將 b.mbackstacknesting 置為 0, 使b在開啟新介面時得到釋放。

做完上述操作,才算真正的將 b destroy 掉而且保證堆疊的正確性。 除此,startfragmentanddestroycurrent還提供了第二個引數, 這個引數是做什麼的呢?是用來控制轉場動畫的。假設 a->b 使用startfragment和轉場動畫 a,b->c 使用startfragmentanddestroycurrent和轉場動畫 b,那麼從 c 返回到 a 時,該使用轉場動畫 a 還是 轉場動畫 b 呢?這就取決於你第二個引數傳什麼了。

fragment執行機制原始碼分析(一)

fragment執行機制原始碼分析(二) 

對fragment的狀態儲存恢復機制原理的分析

對fragment的backstackrecord事務的分析

對fragment、fragmentmanager和backstackrecord的字段全解析

Fragment巢狀以及優化

前言 fragment類似於乙個小片段可以關聯activity完成一些碎片的介面 暫且叫碎片化吧 非常好用。通常乙個activity可以有乙個fragmen他,當然也可以有很多fragment,當fragment多的時候就要考慮fragment巢狀和fragment優化的問題。正文 類似於以上的按鈕...

索引原理和優化

mysql的基本儲存結構是頁 記錄都存在頁裡邊 各個資料頁可以組成乙個雙向鍊錶 每個資料頁中的記錄又可以組成乙個單向鍊錶 使用索引後 沒有用索引我們是需要遍歷雙向鍊錶來定位對應的頁,現在通過 目錄 就可以很快地定位到對應的頁上了!二分查詢,時間複雜度近似為 o logn 其實底層結構就是 b 樹,b...

Fragment和View的比較

fragment和view都有助於介面元件的復用,這在大型工程裡邊是特別重要的,但是二者又有所區別。1 fragment的復用粒度更大。fragment有完整的生命週期,從 設計角度講可以提高內聚性,不同情況下還可以設計不同的fragment,比如橫屏和豎屏情況下view的顯示不一樣,那麼可以建立2...