一次搞懂Fragment的生命周期以及FragmentTransaction的提交方法

一、生命周期简介

Fragment的生命周期和Activity类似,但比Activity的生命周期复杂一些,首先我们来看张图


icon

onAttach():

当Fragment和Activity相关联时调用。可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。

onCreate():

当Fragment被创建时调用。

onCreateView():

当Fragment的布局被创建时调用。

onActivityCreated():

当Activity完成onCreate()时调用。

onStart():

当Fragment可见时调用。

onResume():

当Fragment可见且可交互时调用。

onPause():

当Fragment不可交互但可见时调用。

onStop():

当Fragment不可见时调用。

onDestroyView():

当Fragment的从视图结构中移除时调用。

onDestroy():

当销毁Fragment时调用。

onDetach():

当Fragment和Activity解除关联时调用。

二、生命周期的调用

先看一段代码,介绍一下transaction.addToBackStack(null)这个方法,这个方法是将Fragment加入到回退栈。官方的说法是取决于你是否要在回退的时候显示上一个Fragment。

 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
 transaction.replace(R.id.fragment_view, fragment);
 // transaction.addToBackStack(null);
 transaction.commitAllowingStateLoss();

1.Activity中调用replace()方法时的生命周期

新替换的Fragment:onAttach() > onCreate() > onCreateView() > onViewCreated() > onActivityCreated() > onStart() > onResume()

被替换的Fragment:onPause() > onStop() > onDestroyView() > onDestroy() > onDetach()

2.Activity中调用replace()方法和addToBackStack()方法时的生命周期

新替换的Fragment(没有在BackStack回退栈中):onAttach() > onCreate() > onCreateView() > onViewCreated() > onActivityCreated() > onStart() > onResume()

新替换的Fragment(已经在BackStack回退栈中):onCreateView() > onViewCreated() > onActivityCreated() > onStart() > onResume()

被替换的Fragment:onPause() > onStop() > onDestroyView()

三、FragmentTransaction的提交方法

FragmentTransaction现在提供了四种不同的方法来commit一个transaction:commit()、commitAllowingStateLoss()、commitNow()、commitNowAllowingStateLoss()。

1.commit()

当你调用commit()的时候, FragmentManger会检查是否已经存储了它自己的状态, 如果已经存了, 就抛出IllegalStateException。一旦调用这个方法, 这个commit()并不是立即执行的, 它会被发送到主线程的任务队列当中去, 当主线程准备好执行它的时候执行

2.commitAllowingStateLoss()

当你调用commitAllowingStateLoss()的时候, FragmentManger不会检查是否已经存储了它自己的状态, 也就不会抛出IllegalStateException.有效的解决了commit()提交时出现的问题。

问题::如果你调用的是commitAllowingStateLoss(), 并且是在onSaveInstanceState()之后, 你可能会丢失掉什么状态呢?

答案:你可能会丢掉FragmentManager的状态, 即save之后任何被添加或被移除的Fragments。有同学会疑问,都已经提交了,怎么还会丢失save之后任何被添加或被移除的Fragments呢?因为这个方法是异步的,并不是立即执行。

3.commitNow()

当你调用commitNow()时,将会立即执行并且只会执行你当前要提交的transaction。
从v24.0.0开始提供了 commitNow()方法,在之前开发者会在commit()调用之后加上 executePendingTransactions()来保证立即执行, 即变异步为同步,但是这样会将所有pending在队列中还有你新提交的transactions都执行了,而commitNow()就避免那些你可能并不想执行的transactions。

问题:addToBackStack()和commitNow()是否可以同时使用?

答案:不可以。想想一下, addToBackStack()是把被替换的Fragment放入回退栈中,如果你有一个提交使用了commit(), 紧接着又有另一个提交使用了commitNow(), 两个都想加入back stack, 那back stack会变成什么样呢? 到底是哪个transaction在上, 哪个在下? 答案将是一种不确定的状态, 因为系统并没有提供任何保证来确保顺序, 所以系统决定干脆不支持这个操作。

4.commitNowAllowingStateLoss()

当你调用commitNowAllowingStateLoss()的时候, FragmentManger不会检查是否已经存储了它自己的状态, 也就不会抛出IllegalStateException,并且会立即执行。

在实际开发中怎么去选择使用哪种提交方法呢?

1.如果你操作很多transactions, 并且不需要同步, 或者你需要把transactions加在back stack里, 那就使用commit().
2.如果你需要同步的操作, 并且你不需要加到back stack里, 使用commitNow().
3.当报错“IllegalStateException:Can not perform this action after onSaveInstanceState”时,使用commitAllowingStateLoss()。
4.如果你希望在某一个指定的点, 确保所有的transactions都被执行, 那么使用executePendingTransactions().

END~

你可能感兴趣的:(一次搞懂Fragment的生命周期以及FragmentTransaction的提交方法)