### 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的对应关系如下图**
> * ![](https://img.kancloud.cn/f7/08/f70827d2bfa742cec6c4102b65992894_361x731.png)
> * 推荐文章:
> * [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)