Fragment是什么
Fragment看起来和Activity一样,是一个用户界面。可以结合多个Fragments到一个activity中来构建一个有多方面功能的UI,还可以重用同一个Fragment在多个activities中。Fragment可以当成是activity的一个组件,每个Fragment有单独的生命周期,可以在activity运行时进行添加和移除Fragment。因此,相比较于activity,Fragment更加轻量级,更加灵活。
生命周期方法
onAttach
public void onAttach(@NonNull Context context) {
mCalled = true;
final Activity hostActivity = mHost == null ? null : mHost.getActivity();
if (hostActivity != null) {
mCalled = false;
onAttach(hostActivity);
}
}
public void onAttach(@NonNull Activity activity) {
mCalled = true;
}
onAttach() 是一个 Fragment 和它的 Context 关联时第一个调用的方法,这里我们可以获得对应的Context或者Activity,可以看到这里拿到的Activity是mHost.getActivity(),后面我们介绍FragmentManager 时介绍这个方法。
onCreate()
public void onCreate(@Nullable Bundle savedInstanceState) {
mCalled = true;
restoreChildFragmentState(savedInstanceState);
if (!mChildFragmentManager.isStateAtLeast(Fragment.CREATED)) {
mChildFragmentManager.dispatchCreate();
}
}
void restoreChildFragmentState(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(
FragmentActivity.FRAGMENTS_TAG);
if (p != null) {
mChildFragmentManager.restoreSaveState(p);
mChildFragmentManager.dispatchCreate();
}
}
}
onCreate() 在 onAttach() 后调用,用于做一些初始化操作。需要注意的是,Fragment 的 onCreate() 调用时关联的 Activity 可能还没创建好,所以这里不要有依赖外部 Activity 布局的操作。如果有依赖 Activity 的操作,可以放在onActivityCreate()中。
从上面的代码还可以看到,如果是从旧状态中恢复,会执行子 Fragment 状态的恢复,此外还在onCreate() 中调用了子 Fragment 管理者的创建。
onCreateView()
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
if (mContentLayoutId != 0) {
return inflater.inflate(mContentLayoutId, container, false);
}
return null;
}
在 onCreate() 后就会执行 onCreatView() ,这个方法返回一个 View,默认返回为 null。当我们需要在 Fragment 中显示布局时,需要重写这个方法,返回要显示的布局。 后面布局销毁时就会调用 onDestroyView() 。
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
}
onViewCreate() 不是生命周期中的方法,但是却很有用。它会在 onCreateView() 返回后立即执行,参数中的 view 就是之前创建的 View,因此我们可以在onViewCreate() 中进行布局的初始化.
onActivityCreated
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
mCalled = true;
}
onActivityCreated() 会在 Fragment 关联的 Activity 创建好、Fragment 的布局结构初始化完成后调用。可以在这个方法里做些和布局、状态恢复有关的操作.
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
mCalled = true;
}
onViewStateRestored() 方法会在 onActivityCreated() 结束后调用,用于一个 Fragment 在从旧的状态恢复时,获取状态 saveInstanceState 恢复状态,比如恢复一个 check box 的状态。经过这四步,Fragment 创建完成,同步于 Activity 的创建过程.
onStart()
@MainThread
@CallSuper
public void onStart() {
mCalled = true;
}
onStart() 当 Fragment 可见时调用,同步于 Activity 的 onStart() 。
onResume()
@MainThread
@CallSuper
public void onResume() {
mCalled = true;
}
onResume()当Fragment 可见并且可以与用户交互时调用。它和Activity的onResume()同步。
onPause()
@MainThread
@CallSuper
public void onPause() {
mCalled = true;
}
onPause() 当 Fragment 不再可见时调用。也和 Activity 的 onPause() 同步。
onStop()
@MainThread
@CallSuper
public void onStop() {
mCalled = true;
}
onStop() 当 Fragment 不再启动时调用,和 Activity.onStop() 一致。
onDestroyView()
@MainThread
@CallSuper
public void onDestroyView() {
mCalled = true;
}
当onCreateView()返回的布局(不论是不是null)从Fragment中解除绑定时调用 onDestroyView().下次 Fragment 展示时,会重新创建布局。
onDestroy()
@MainThread
@CallSuper
public void onDestroy() {
mCalled = true;
}
当 Fragment 不再使用时会调用 onDestroy() ,它是一个 Fragment 生命周期的倒数第二步。可以看到这里,调用了 mLoaderManager.doDestroy().
onDetach()
@MainThread
@CallSuper
public void onDetach() {
mCalled = true;
}
Fragment 生命周期的最后一个方法,当 Fragment 不再和一个 Activity 绑定时调用。 Fragment 的 onDestroyView() , onDestroy() , onDetach() 三个对应Activity 的 onDestroyed()方法。
fragment整体架构图
- FragmentActivity 是 Activity 支持 Fragment 的基础,其中持有一个 FragmentController 中间类,它是 FragmentActivity 和 FragmentManager 的中间桥接者,对 Fragment 的操作最终是分发到 FragmentManager 来处理;
- FragmentManager 承载了 Fragment 的核心逻辑,负责对 Fragment 执行添加、移除或替换等操作,以及添加到返回堆栈。它的实现类 FragmentManagerImpl 是我们主要的分析对象;
- FragmentHostCallback 是 FragmentManager 向 Fragment 宿主的回调接口,Activity 和 Fragment 中都有内部类实现该接口,所以 Activity 和 Fragment 都可以作为另一个 Fragment 的宿主(Fragment 宿主和 FragmentManager 是 1 : 1 的关系);
- FragmentTransaction 是 Fragment 事务抽象类,它的实现类BackStackRecord 是事务管理的主要分析对象。
宿主与关联的 FragmentManager 的关系
Fragment的五种状态
- static final int INITIALIZING = 0; 初始状态,Fragment 未创建
- static final int CREATED = 1; 已创建状态,Fragment 视图未创建
- static final int ACTIVITY_CREATED = 2; 已视图创建状态,Fragment 不可见
- static final int STARTED = 3; 可见状态,Fragment 不处于前台
- static final int RESUMED = 4; 前台状态,可接受用户交互
事务
BackStackRecord 继承了 FragmentTransaction :
final class BackStackRecord extends FragmentTransaction implements
FragmentManager.BackStackEntry, FragmentManager.OpGenerator {
}
FragmentTransaction 定义了一系列对 Fragment 的操作方法:
//它会调用 add(int, Fragment, String),其中第一个参数传的是 0
public abstract FragmentTransaction add(Fragment fragment, String tag);
//它会调用 add(int, Fragment, String),其中第三个参数是 null
public abstract FragmentTransaction add(@IdRes int containerViewId,
Fragment fragment);
//添加一个 Fragment 给 Activity 的最终实现
//第一个参数表示 Fragment 要放置的布局 id
//第二个参数表示要添加的 Fragment,【注意】一个 Fragment 只能添加一次
//第三个参数选填,可以给 Fragment 设置一个 tag,后续可以使用这个 tag 查询它
public abstract FragmentTransaction add(@IdRes int containerViewId,
Fragment fragment,@Nullable String tag);
//调用 replace(int, Fragment, String),第三个参数传的是 null
public abstract FragmentTransaction replace(@IdRes int containerViewId,Fragment fragment);
//替换宿主中一个已经存在的 fragment
//这一个方法等价于先调用 remove(), 再调用 add()
public abstract FragmentTransaction replace(@IdRes int containerViewId,Fragment fragment,@Nullable String tag);
//移除一个已经存在的 fragment
//如果之前添加到宿主上,那它的布局也会被移除
public abstract FragmentTransaction remove(Fragment fragment);
//隐藏一个已存的 fragment
//其实就是将添加到宿主上的布局隐藏
public abstract FragmentTransaction hide(Fragment fragment);
//显示前面隐藏的 fragment,这只适用于之前添加到宿主上的 fragment
public abstract FragmentTransaction show(Fragment fragment);
//将指定的 fragment 将布局上解除
//当调用这个方法时,fragment 的布局已经销毁了
public abstract FragmentTransaction detach(Fragment fragment);
//当前面解除一个 fragment 的布局绑定后,调用这个方法可以重新绑定
//这将导致该 fragment 的布局重建,然后添加、展示到界面上
public abstract FragmentTransaction attach(Fragment fragment);
对 fragment 的操作基本就这几步,我们知道,要完成对 fragment 的操作,最后还需要提交一下.
事务的提交方式:
- commit() 在主线程中异步执行,其实也是 Handler 抛出任务,等待主线程调度执行。
- commitAllowingStateLoss() 异步执行,但它的不同之处在于,允许在 Activity 保存状态之后调用,也就是说它遇到状态丢失不会报错。
- commitNow() 是同步执行的,立即提交任务。
- commitNowAllowingStateLoss() 同步执行
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。