### Fragment
#### 1、談一談Fragment的生命周期?
> * 參考回答:
> * Fragment從創建到銷毀整個生命周期中涉及到的方法依次為:onAttach()→onCreate()→ onCreateView()→onActivityCreated()→onStart()→onResume()→onPause()→onStop()→onDestroyView()→onDestroy()→onDetach(),其中和Activity有不少名稱相同作用相似的方法,而不同的方法有:
> * **onAttach()**:當Fragment和Activity建立關聯時調用;
> * **onCreateView()**:當Fragment創建視圖調用,在onCreate之后;
> * **onActivityCreated()**:當與Fragment相關聯的Activity完成onCreate()之后調用;
> * **onDestroyView()**:在Fragment中的布局被移除時調用;
> * **onDetach()**:當Fragment和Activity解除關聯時調用;
> * **Fragment的生命周期與Activity的對應關系如下圖**
> * 
> * 推薦文章:
> * [Android之Fragment優點](https://www.cnblogs.com/shaweng/p/3918985.html)
#### 2、談談Activity和Fragment的區別?
> * 參考回答:
> * 相似點:都可包含布局、可有自己的生命周期
> * 不同點:
> * Fragment相比較于Activity多出4個回調周期,在控制操作上更靈活;
> * Fragment可以[在XML文件中直接進行寫入](https://developer.android.google.cn/training/basics/fragments/creating#AddInLayout),也可以在Activity中動態添加;
> * Fragment可以使用show()/hide()或者replace()隨時對Fragment進行切換,并且切換的時候不會出現明顯的效果,用戶體驗會好;Activity雖然也可以進行切換,但是Activity之間切換會有明顯的翻頁或者其他的效果,在小部分內容的切換上給用戶的感覺不是很好;
#### 3、Fragment中add與replace的區別(Fragment重疊)
> * 參考回答:(add與replace是FragmentTransaction的方法,[在運行時為 Activity 添加 Fragment](https://developer.android.google.cn/training/basics/fragments/fragment-ui#AddAtRuntime),[替換 Fragment](https://developer.android.google.cn/training/basics/fragments/fragment-ui#Replace))
> * [add 和 replace 如何選擇?](https://juejin.im/post/5e5cd8686fb9a07cbc269d10#heading-5)
> * 在我們的`activity`中,我們有一個容器,其中裝有`fragment`。
> * `add`只會將一個`fragment`添加到容器中。 假設您將`FragmentA`和`FragmentB`添加到容器中。 容器將具有`FragmentA`和`FragmentB`,如果容器是`FrameLayout`,則將`fragment`一個添加在另一個之上。
> * `replace`將簡單地替換容器頂部的一個`fragment`,因此,如果我創建了 `FragmentC`并 `replace` 頂部的 `FragmentB`,則`FragmentB`將被從容器中刪除(執行`onDestroy`,除非您調用`addToBackStack`,僅執行`onDestroyView`),而`FragmentC`將位于頂部。
> * 那么如何選擇呢? `replace`刪除現有`fragment`并添加一個新`fragment`。 這意味著當您按下返回按鈕時,將創建被替換的`fragment`(原先就存在的`fragment`),并調用其`onCreateView`。 另一方面,`add`保留現有`fragment`,并添加一個新`fragment`,這意味著現有`fragment`將處于活動狀態,并且它們不會處于 “paused” 狀態。 因此,按下返回按鈕時,現有`fragment`(添加新`fragment`之前的`fragment`)不會調用`onCreateView`。 就`fragment`的生命周期事件而言,在`replace`的情況下將調用`onPause`,`onResume`,`onCreateView`和其他生命周期事件,在`add`的情況下則不會。
> * 如果不需要重新訪問當前`fragment`并且不再需要當前`fragment`,請使用`replace`。 另外,如果您的應用有內存限制,請考慮使用`replace`。
> * add不會重新初始化Fragment,replace每次都會。所以如果在Fragment生命周期內獲取獲取數據,使用replace會重復獲取;
> * 添加相同的Fragment時,replace不會有任何變化,add會報IllegalStateException異常;
> * replace先remove掉相同id的所有Fragment,然后在add當前的這個Fragment,而add是覆蓋前一個Fragment。所以如果使用add一般會伴隨hide()和show(),避免布局重疊;
> * 使用add,如果應用放在后臺,或以其他方式被系統銷毀,再打開時,hide()中引用的Fragment會銷毀,所以依然會出現布局重疊bug,可以使用replace或使用add時,添加一個tag參數;
```
//Fragment布局重疊解決方案,方法不唯一,僅供參考
private int mCurrentPos=-1;
private List<Fragment> mFragments =new ArrayList<>();
private void switchFragmentIndex(int position){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if(mCurrentPos !=-1){
transaction.hide(mFragments.get(mCurrentPos));
}
if(!mFragments.get(position).isAdded()){//避免Fragment重復添加
transaction.add(R.id.fl_content,mFragments.get(position));
}
transaction.show(mFragments.get(position)).commit();
mCurrentPos =position;//記錄當前Fragment下標
}
```
#### 4、getFragmentManager(已棄用)、getSupportFragmentManager 、getChildFragmentManager、getParentFragmentManager之間的區別?
> * 參考回答:
> * [getSupportFragmentManager , getParentFragmentManager和getChildFragmentManager](https://juejin.im/post/5e5cd8686fb9a07cbc269d10#heading-1)
> * 首先要確認一件事,`getSupportFragmentManager()`是 `FragmentActivity`下的方法
> * `getParentFragmentManager` 和 `getChildFragmentManager` 是 `androidx.fragment.app.Fragment` 下的方法,**其中 `androidx.fragment 1.2.0` 后 `getFragmentManager` 與 `requireFragmentManager` 已棄用**
> * `getSupportFragmentManager`與 `activity`關聯,可以將其視為 `activity` 的 `FragmentManager`
> * `getChildFragmentManager` 與 `fragment`關聯,可以將其視為`fragment`的`FragmentManager`
> * `getParentFragmentManager`情況稍微復雜,正常情況返回的是該`fragment` 依附的`activity`的`FragmentManager`。如果該fragment是另一個`fragment` 的子 `fragment`,則返回的是其父`fragment`的 `getChildFragmentManager`
> * getFragmentManager()所得到的是所在Fragment 的**父容器**的管理器, getChildFragmentManager()所得到的是在Fragment 里面**子容器**的管理器, 如果是Fragment嵌套Fragment,那么就需要利用getChildFragmentManager();
> * 推薦文章
> * [【背上Jetpack之Fragment】你真的會用Fragment嗎?Fragment常見問題以及androidx下Fragment的使用新姿勢](https://juejin.im/post/5e5cd8686fb9a07cbc269d10)
> * [AndroidX 概覽](https://developer.android.google.cn/jetpack/androidx)
> * [遷移到 AndroidX](https://developer.android.google.cn/jetpack/androidx/migrate)
> * [是時候遷移至 AndroidX 了!](https://mp.weixin.qq.com/s/ENVktd-2g3cwixVeUi33AA)
> * [androidx中的fragment API](https://developer.android.google.cn/jetpack/androidx/releases/fragment)
> * [androidx中的fragment API 版本 1.2.0](https://developer.android.google.cn/jetpack/androidx/releases/fragment#version\_120\_3)
> * **棄用`getFragmentManager()`**:棄用了關于 Fragment 的`getFragmentManager()`和`requireFragmentManager()`方法,并替換為單個`getParentFragmentManager()`方法,后者會返回添加了 Fragment 的非 null`FragmentManager`(您可以使用`isAdded()`來確定是否可以安全調用該方法)
#### 5、[FragmentPagerAdapter](https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/support/fragment/src/main/java/androidx/fragment/app/FragmentPagerAdapter.java)與[FragmentStatePagerAdapter](https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/support/fragment/src/main/java/androidx/fragment/app/FragmentStatePagerAdapter.java)的區別與使用場景
> * 參考回答:
> * 相同點 :二者都繼承PagerAdapter
> * 不同點 :
> * **FragmentPagerAdapter**的每個Fragment會持久的保存在FragmentManager中,只要用戶可以返回到頁面中,它都不會被銷毀。因此適用于那些數據**相對靜態**的頁,Fragment**數量也比較少**的那種; **FragmentStatePagerAdapter**只保留當前頁面,當頁面不可見時,該Fragment就會被消除,釋放其資源。因此適用于那些**數據動態性**較大、**占用內存**較多,多Fragment的情況;
> * **FragmentPagerAdapter**將整個 `fragment`存儲在內存中,如果`ViewPager`中使用了大量 `fragment`,則可能導致內存開銷增加。 **FragmentStatePagerAdapter**僅存儲片段的`savedInstanceState`,并在失去焦點時銷毀所有 `fragment`。
> * 推薦文章
> * [FragmentStatePagerAdapter和 FragmentPagerAdapter](https://juejin.im/post/5e5cd8686fb9a07cbc269d10#heading-2)