文章里所有分析都是根據Android Sdk 25.3.1 v4包
經過前面幾篇對 FragmentManager 源碼的分析,對 mAdded
和 mActive
這兩個屬性有了一定的理解,下面是在 StackOverFlow 上的一個問題,詳細的總結了這兩個屬性的具體差異。
mAdded:
- 包含了所有已經 added 并且沒有被從 Activity 中 removed 和 detached 的 Fragments。
- 這些 Fragment 在視圖交互上有如下特性:
- 對下面事件作出反應:
- 低內存事件
- configuration changes (比如屏幕旋轉)
- 展示自定義 menu 并對 menu 的點擊作出回應
onMenuItemSelected()
。 - Fragment 的生命周期響應它宿主 Activity 的生命周期
- 對下面事件作出反應:
- 不在
mAdded
中的 Fragments 不能對事件作出相應和展示自定義的 menu。
mActive:
mAdded
的一個超集,是綁定到一個 Activity 上的所有 Fragment。包括返回棧中所有的通過任何 FragmentTransaction
添加的 Fragments。這是非常重要的因為如下原因:
- 當一個 Activity 要保存它的 State 時,它必須保存它所有 Fragment 的狀態,因為
mActive
保存了所有 Fragment,所以系統只要存儲這個列表里的 Fragment 的狀態就好了。而mAdded
只是被序列化成一個整形數組,每個元素指向 Fragment 在mActive
中的下標位置(這塊在前面 Fragment 的存儲與恢復中分析到了)。 - 在恢復 Activity 的狀態時,FragmentManager 的狀態也會被恢復,
mActive
列表就可以被用來恢復mAdded
列表,因為保存狀態的時候mAdded
被簡單的保存為整形數組。 - 當一個 Activity 經歷它的各生命周期時,它必須引起所有綁定的 Fragment 經歷各自的生命周期。
- 該 Activity 的 FragmentManager 有義務去引導所有 Fragemnt 轉換到正確的狀態,這其中包括屏幕上可見的 Fragment 的 View 層級的初始化,并且調用正確的生命周期函數。
- 為了確保完整,FragmentManager 將遍歷
mActive
中所有的 Fragment,而不僅僅是mAdded
。
- 它持有所有 BackStack 返回棧引用的對象。
- 這確保了返回棧中對 Fragment 操作的回滾能夠實現。
什么情況下這兩個 Fragment 的列表會變動呢?
-
mAdded
- 如果一個 Fragment 被添加到 Activity 中,那么這個 Fragment 會被 added 到該列表。
- Fragment 被從該列表中移除:
- Fragment 被從 Activity 中 removed。
- Fragment 從 Activity 中 detached。
-
mActive:
- 如果一個 Fragment 被添加到 Activity 中,那么這個 Fragment 會被 added 到該列表。
-
只有在下面這兩種情況 Fragment 才會被從該列表中移除:
- Fragment 被從 Activity 中移除,并且沒有在返回棧中。
- 一個 transaction 從返回棧中被 pop 出來、 Fragment 的 add 或者 replace 操作被逆向,即返回棧不再持有該 Fragment。
-
結論
mAdded
是 alive in a sense (在感官上存活的),而mActive
是所有綁定在 Activity 上的 Framgent 列表。mActive
包括 alive Fragments (mAdded
) 和 freeze dried (冷凍儲存) Fragments (仍然在返回棧中等待被恢復)。繼續對比活著的和冷凍儲存的實體的區別:當 activities 觸發回調函數比如
onConfigurationChanged()
活著onLowMemory()
,真正關系這些回調事件的只是活著的 Fragments。所以你會發現在
FragmentManagerImpl
回調只會遍歷mAdded
即活著的 Fragments。fragmentManager.dispatchLowMemory()
在activity.onLowMemory()
中被調用。public void dispatchLowMemory() { if (mAdded != null) { for (int i=0; i<mAdded.size(); i++) { Fragment f = mAdded.get(i); if (f != null) { f.performLowMemory(); } } } }
?