Fragment 简单了解
Fragment
的生命周期
答案参考自:
可以看到 Fragment 的生命周期和 Activity 很相似,只是多了一下几个方法:
onAttach()
在Fragment 和 Activity 建立关联时调用(Activity 传递到此方法内)。
onCreateView()
当Fragment 创建视图时调用。
onActivityCreated()
在相关联的 Activity 的 onCreate() 方法已返回时调用。
onDestroyView()
当Fragment中的视图被移除时调用。
onDetach()
当Fragment 和 Activity 取消关联时调用。
几种操作情况下Fragment 的生命周期变化
结合Activity
的生命周期
管理 Fragment 生命周期和 Activity 生命周期很相似,同时 Activity 的生命周期对 Fragment 的生命周期也有一定的影响,如下图所示。
用下图(来源)来表示 Activity 和 Fragment 的生命周期变化的先后过程是:
Fragment 生命周期与 Activity 生命周期的一个关键区别就在于,Fragment 的生命周期方法是由托管Activity而不是操作系统调用的。Activity 中生命周期方法都是 protected,而 Fragment 都是 public,也能印证了这一点,因为 Activity 需要调用 Fragment 那些方法并管理它。
Activity
和Fragment
的通信方式
答案参考自:
将Fragment添加到Activity之后,Fragment必须与Activity交互信息,这就需要Fragment能获取它所在的Activity,Activity也能获取它所包含的任意的Fragment。
Fragment获取它所在的Activtiy
调用Fragment的getActivity()方法即可返回它所在的Activity。
Activity获取它包含的Fragment
调用Activity关联的FragmentManager的findFragmentById(int id)或findFragmentByTag(String tag)方法即可获取指定的Fragment。
除此之外,Fragment与Activity可能还需要相互传递数据,可按如下方式进行。
Activity向Fragment传递数据
在Activity中创建Bundle数据包,并调用Fragment的setArguments(Bundle bundle)方法即可将Bundle数据包传给Fragment。
Fragment向Activity传递数据或Activity需要在Fragment运行中进行实时通信
在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口,这样Fragment即可调用该回调方法将数据传给Activity。
使用 FragmentManager 还可以执行的操作包括:
- 通过 findFragmentById 或 findFragmentByTag 获取 activity 中存在的 fragment 的实例
- 通过 popBackStack (模拟用户点击返回按钮操作)将 fragment 从返回栈中弹出
- 通过 addOnBackStackChangedListener() 注册一个监听返回栈改变的监听器
- 像上边生成 fragmentTransaction 的方法,可以使用 fragmentManager 生成一个 fragmentTransaction 来执行某些事务,比如添加、替换、移除、addToBackStack()等。
Fragment
之间如何进行通信
答案参考自:
Activity 中的两个或更多 Fragment 需要相互通信是一种很常见的现象。想象一下拆分视图 (list-detail
) Fragment 的常见情况,假设您有一个 Fragment,在该 Fragment 中,用户从列表中选择一项,还有另一个 Fragment,用于显示选定项的内容。这种情况不太容易处理,因为这两个 Fragment 都需要定义某种接口描述,并且所有者 Activity 必须将两者绑定在一起。此外,这两个 Fragment 都必须处理另一个 Fragment 尚未创建或不可见的情况。
可以使用 ViewModel
对象解决这一常见的难点。这两个 fragment 可以使用其 activity 范围共享 ViewModel
来处理此类通信,如以下示例代码所示:
1 |
|
请注意,这两个 Fragment 都会检索包含它们的 Activity。这样,当这两个 Fragment 各自获取 ViewModelProvider
时,它们会收到相同的 SharedViewModel
实例(其范围限定为该 Activity)。
此方法具有以下优势:
- Activity 不需要执行任何操作,也不需要对此通信有任何了解。
- 除了
SharedViewModel
约定之外,Fragment 不需要相互了解。如果其中一个 Fragment 消失,另一个 Fragment 将继续照常工作。 - 每个 Fragment 都有自己的生命周期,而不受另一个 Fragment 的生命周期的影响。如果一个 Fragment 替换另一个 Fragment,界面将继续工作而没有任何问题。
为什么使用Fragment.setArguments(Bundle)
传递参数
答案参考自:
当我们实例化自定义Fragment时,为什么官方推荐Fragment.setArguments(Bundle bundle)这种方式来传递参数,而不推荐通过构造方法直接来传递参数呢?
方式一:通过构造方法传递参数
在创建Fragment的时候,使用 MyFragment fragment = new MyFragment(parameter) 来传递参数。
1 |
|
方式二:通过Fragment.setArguments(Bundle)传递参数
在创建Fragment的时候,使用MyFragment fragment = MyFragment.newInstance(paramter) 来传递参数。
1 |
|
结论
我们可以知道Activity重新创建时,会重新构建它所管理的Fragment,原先的Fragment的字段值将会全部丢失,但是通过 Fragment.setArguments(Bundle bundle)方法设置的bundle会保留下来。所以尽量使用Fragment.setArguments(Bundle bundle)方式来传递参数。
Fragment
嵌套问题
答案参考自:
嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment。
使用时, 主要要依靠宿主Fragment的 getChildFragmentManager() 来获取FragmentManger。 虽然看起来和在activity中添加fragment差不多, 但因为fragment生命周期及管理恢复模式不同, 其中有一些需要特别注意的地方。
本文内容还包括了从Fragment迁移到v4.Fragment代码中需要改动的一些地方.
嵌套Fragments
嵌套Fragments 是Android 4.2 API 17 引入的.
目的: 进一步增强动态复用。
嵌套Fragment的动态添加
在宿主fragment里调用getChildFragmentManager()
即可用它来向这个fragment内部添加fragments。
1 |
|
同样, 对于内部的fragment来说, getParentFragment() 方法可以获取到fragment的宿主fragment.
getChildFragmentManager() 和 getFragmentManager()
getChildFragmentManager()是fragment中的方法, 返回的是管理当前fragment内部子fragments的manager.
getFragmentManager()在activity和fragment中都有。
在activity中, 如果用的是v4 support库, 方法应该用getSupportFragmentManager(), 返回的是管理activity中fragments的manager.
在fragment中, 调用getFragmentManager(), 返回的是把自己加进来的那个manager.
也即, 如果fragment在activity中, fragment.getFragmentManager()得到的是activity中管理fragments的那个manager.
如果fragment是嵌套在另一个fragment中, fragment.getFragmentManager()得到的是它的parent的getChildFragmentManager()。
总结就是: getFragmentManager()是本级别管理者, getChildFragmentManager()是下一级别管理者。这实际上是一个树形管理结构。
TODO
FragmentPageAdapter
和FragmentStatePageAdapter
区别及使用场景