1. android.app.Fragment 與 android.support.v4.app.Fragment
Fragment有不同的Library做處理
v4版本的出現是為了要支援Android 3.0以前的版本
也就是說支援的系統版本只要是3.0以上就建議直接使用原生的 app.Fragment
然而原生的app.Fragment有使用上的一些限制
例如 FragmentManager 中 getFragments() 限定為 Android 8.0 以上才支援
最近因為專案上的需求又跑回去看了一次Fragment的東西
發現官網上app.Fragment的頁面上標示了一條訊息 ( 如下圖 )
來源:https://developer.android.com/reference/android/app/Fragment
在API 28之後 app.Fragment 就不建議被使用了
建議使用 Support Library 獲得更良好的跨裝置支援性
所以之前開檔案手賤全換成 app.Fragment 這下要全換回來
不過也好,原本使用 app.Fragment 時發生的一些怪問題似乎都解決了
2. android.support.v4.app.Fragment 使用上的注意事項
v4版本的Fragment 使用時需要透過 getSupportFragmentManager() 取得管理器
而不是getFragmentManager()
3. 關於 add、hide、show、remove與replace
Fragment 提供幾個控制的方法,如同小標題所示
replace使用上最簡單直覺,意思就是替換掉目前畫面的Fragment
例如,將FragmentA移除 -> 加入FragmentB -> 顯示FragmentB
整個過程動用到 add、remove與show
會跑過Fragment完整的生命流程
而使用add、remove與show流程上就比較繁瑣,相對來說會有最大的彈性
重點在於要自行控制各Fragment顯示與隱藏
例如目前是顯示FragmentA,想要替換成FragmentB
結果沒有將FragmentA收起來( hide )就直接顯示FragmentB
這樣會導致兩個Fragment交疊在一起 ( 同時顯示兩個畫面 )
重點在於FragmentA只是收起來不顯示而已
並不會觸發Fragment的完整生命流程,除非被系統強制回收之類的
至於要使用哪一個方法來就看自己的情況
如果Fragment有高頻率重複使用的特性,建議是用 show 與 hide
反之僅一兩次的話可以使用 replace
4. 關於 popBackStack
popBackStack(String name, int flags)
name 可以為字串或者null
flags則有 0 與 FragmentManager.POP_BACK_STACK_INCLUSIVE 兩種參數
基本上會有以下的狀況
=== name 為null的情況下 ===
flags為0
pop出BackStack最上層的Fragment
flags為 FragmentManager.POP_BACK_STACK_INCLUSIVE
pop出BackStack中所有的Fragment
=== name 不為null的情況下 ===
會以該Tag相對應的Fragment為基準
flags為 0
pop出該Tag以上的Fragment
flags為 FragmentManager.POP_BACK_STACK_INCLUSIVE
pop出包含該Tag以上的Fragment
5. 關於Fragment重疊 ( Overlapping ) 的解決辦法
Fragment有一個地方要注意,由於Fragment需要依賴Activity來顯示因此Fragment的生命週期與Activity緊緊相扣
當Fragment退回背景或者Activity被系統回收之類的事情發生
例如畫面翻轉時,Activity會重新跑一次生命週期
因而嚴重影響到Fragment的運作
相關的預防方法如下
a. 重新指定Fragment物件
Activity重啟之後,Fragment畫面雖然會保留,但原先的變數資料會消失
因此需要透過下列的方法來重新指定Fragment
b. 保存特定的Fragment
在實驗專案中,使用一個currentFragment來記錄當下畫面所顯示的Fragment
而Activity重啟之後currentFragment會變成null的情況
但這個狀況可以透過下列的程式碼來處理
onSaveInstanceState(Bundle outState)方法中
透過FragmentManager的putFragment()方法來儲存指定的Fragment
( 如同處理Bundle一樣 )
而在onCreate(Bundle saveInstanceState)方法中
先判斷 saveInstanceState 物件是否為 null
如果不為空則透過FragmentManager物件的getFragment()方法取出先前儲存的Fragment
然後這段可以再寫嚴謹一點,取出Fragment時還可以再次檢查是否為 null
c. 設定Layout的背景顏色
最懶惰的辦法
6. 如何得知目前畫面的Fragment是哪一個,可套用於onBackPressed處理
FragmentManage物件可以設定監聽OnBackStackChangedListener()當BackStack有變化時便會觸發
透過這樣的特性來檢查目前的Fragment是哪一個
先使用 getBackStackEntryCount() -1 來取得最上層Fragment的Index
再使用Index透過getBackStackEntryAt()方法來取得Fragment便於取的其Tag字串
最後使用Tag字串找出最上層的Fragment,將其設定為 currentFragment
上圖所示的程式碼
popFragment()當中,除了執行popBackStack()之外
也會回傳popBackStack後的 BackStack Size
在 onBackPressed() 中 if 的判斷意思
當 BackStack 剩下一個時,便呼叫父類別的 onBackpressed() 方法
跳出當前的 Activity
沒有留言:
張貼留言