Fragment是Android的视图生命周期控制器(带生命周期的自定义View),是Activity上的View层级中的一部分,通常能够把它看作一个轻量级的Activity.与传统的Activity相比,它只占用更少的资源,而且提供更大的编码灵活性、在超低版本上的兼容性等.java
使用 Fragment 能获得较好的运行效果,而且能将过渡动画兼容到更低的版本(经过FragmentTransition指定)。android
单Activity多Fragment模式.使用这种模式有许多好处:api
Fragment有两种方式生成,一是硬编码到xml文件中,二是在Java代码中new,而后经过FragmentManager#beginTransaction开启FragmentTransaction提交来添加Fragment.两种方式存在着必定区别.硬编码到xml的Fragment没法被FragmentTransition#remove移除,与Activity同生共死,因此你要是这么用了,就不用试了,移除不了的,可是在代码中new出来的是能够被移除的.数组
直接硬编码到xml中:bash
<fragment
android:id="@+id/map_view"
android:name="org.kexie.android.dng.navi.widget.AMapCompatFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
复制代码
添加Fragment的第二种方式就是使用FragmentManager#beginTransaction(代码以下)动态添加,你须要先new一个Fragment,而后经过下面Fragment#requireFragmentManager获取FragmentManager来使用beginTransaction添加Fragment,注意add方法的第一个参数,你须要给它指定一个id,也就是Fragment容器的id,一般容器是一个没有子View的FrameLayout,它决定了这个Fragment要在什么位置显示.app
//在xml中编写放置Fragment位置的容器
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
//在java代码中动态添加Fragment
requireFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.runOnCommit(()->{/*TODO*/})
.addToBackStack(null)
.commit();
复制代码
在Fragment中,咱们可使用getId()能够返回自身的id,一般用这个方法返回它所在的容器的id,供其余Fragment添加进也添加到当前容器时使用(例如使用Fragment返回栈的场景)。框架
/**
* Return the identifier this fragment is known by. This is either
* the android:id value supplied in a layout or the container view ID
* supplied when adding the fragment.
*/
final public int getId() {
return mFragmentId;
}
复制代码
须要注意的是FragmentTransaction并非当即执行的,而是在当前代码执行完毕后,回到事件循环(也就是大家知道的Looper)时,才会执行,不过他会保证在下一帧渲染以前获得执行(经过Handler#createAsync机制),若要在FragmentTransaction执行时搞事情,你须要使用runOnCommit,在上面的代码中我使用了Java8的lambda表达式简写了Runnable.异步
若是你还想使用Fragment回退栈记得调用addToBackStack,最后别忘了commit,这样才会生效,此时commit函数返回的是BackStackEntry的idide
固然FragmentTransaction不止能够执行add操做,一样也能够执行remove,show,hide等操做.函数
onBackPressed在哪?我知道第一次使用Fragment的人确定都超想问这个问题.众所周知Fragment自己是没有onBackPressed的.不是Google不设计,而是真的无法管理啊!!!,若是一个界面上有三四个地方都有Fragment存在,一按回退键,谁知道要交给哪一个Fragment处理呢?因此Fragment自己是没有onBackPressed的.可是,实际上给Fragment添加相似onBackPressed的功能的办法是存在的,只是Google把它设计成交给开发者自行管理了.
这个功能是彻底基于Google的appcompat包实现的,可是如果咱们想要使用这个功能,可能须要较高版本的appcompat包,或者你把项目迁移到AndroidX(迁移方式下面会介绍).
咱们可使用FragmentActivity(AppCompatActivity继承了FragmentActivity)的addOnBackPressedCallback方法为你的Fragment提供拦截OnBackPressed的功能了.(非AndroidX的其余版本可能也有实现了这个功能)
public void addOnBackPressedCallback(@NonNull LifecycleOwner owner,
@NonNull OnBackPressedCallback onBackPressedCallback)
复制代码
OnBackPressedCallback#handleOnBackPressed须要返回一个boolean值。若是你在这个回调里拦截了onBackPressed应该返回true,说明你本身已经处理了本次返回键按下的操做,这样你的Fragment就不会被弹出返回栈了。
值得注意的是,这个函数的第一个参数,一个LifecycleOwner,Activity和Fragment都是LifecycleOwner,用于提供组件的生命周期,这个参数能够帮咱们自动管理OnBackPressedCallback回调,你无需手动将他从Activity中移除,在LifecycleOwner的ON_DESTROY事件来到的时候,他会被自动移除列表,你无需担忧内存泄漏,框架会帮你完成这些事情。
/**
* Interface for handling {@link ComponentActivity#onBackPressed()} callbacks without
* strongly coupling that implementation to a subclass of {@link ComponentActivity}.
*
* @see ComponentActivity#addOnBackPressedCallback(LifecycleOwner, OnBackPressedCallback)
* @see ComponentActivity#removeOnBackPressedCallback(OnBackPressedCallback)
*/
public interface OnBackPressedCallback {
/**
* Callback for handling the {@link ComponentActivity#onBackPressed()} event.
*
* @return True if you handled the {@link ComponentActivity#onBackPressed()} event. No
* further {@link OnBackPressedCallback} instances will be called if you return true.
*/
boolean handleOnBackPressed();
}
复制代码
咱们能够看到Activity内管理的OnBackPressedCallback的执行循序与添加时间有关.最后被添加进去的能最早获得执行.
public void addOnBackPressedCallback(@NonNull LifecycleOwner owner,
@NonNull OnBackPressedCallback onBackPressedCallback) {
Lifecycle lifecycle = owner.getLifecycle();
if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {
// Already destroyed, nothing to do
return;
}
// Add new callbacks to the front of the list so that
// the most recently added callbacks get priority
mOnBackPressedCallbacks.add(0, new LifecycleAwareOnBackPressedCallback(
lifecycle, onBackPressedCallback));
}
复制代码
能够看到它是添加到mOnBackPressedCallbacks这个List的最前面的.
startFragmentForResult方法在哪?对不起和OnBackPressed同样,Google没有直接为咱们实现这个方法,但这并不表明Fragment没有这个功能,你固然能够直接用定义getter的方式来获取Fragment上内容,但这并非最佳实践,为了规范编码咱们最好仍是使用公共的API
Fragment#setTargetFragment能够给当前Fragment设置一个目标Fragment和一个请求码
public void setTargetFragment(@Nullable Fragment fragment, int requestCode)
复制代码
当当前Fragment完成相应的任务后,咱们能够这样将返回值送回给咱们的目标Fragment经过Intent
getTargetFragment().onActivityResult(getTargetRequestCode(),
Activity.RESULT_OK,new Intent());
复制代码
不过要注意,目标Fragment和被请求的Fragment必须在同一个FragmentManager的管理下,不然就会报错
好了若是你如今使用的appcompat包没有上面的骚操做.那么下面我将带你迁移到AndroidX.
这里可能有人会问AndroidX是什么?
简单来说AndroidX就是一个与平台解绑的appcompat(低版本兼容高版本功能)库,也就是说在build.gradle中不须要再与compileSdkVersion写成同样,例如以前这样的写法:
compile 'com.android.support:appcompat-v7:24.+'
复制代码
(注:使用24.+则代表使用 24. 开头的版本的最新版本,若直接使用+号则代表直接使用该库的最新版本。
如今能够写成:
implementation 'androidx.appcompat:appcompat:1.1.0-alpha02'
复制代码
(注:新的依赖方式implementation与compile功能相同,可是implementation没法在该模块内引用依赖的依赖,但compile能够,这么作的好处是能够加快编译速度。新的依赖方式api与compile彻底相同,只是换了名字而已)
在Android Studo3.0以上中的Refactor->Migrate to AndroidX的选点击以后便可将项目迁移到AndroidX,在确认的时会提示你将项目备份以避免迁移失败时丢失原有项目,一般状况下不会迁移失败,只是迁移的过程会花费不少的时间,若是项目很大,迁移时间会很长,这时即便Android Studio的CPU利用率为0也不要关闭, 可是若是发生迁移失败,这时候就须要手动迁移了。
一些使用gradle依赖的一些第三方库中的某些类可能继承了android.support.v4包下的Fragment,但迁移到AndroidX后appcompat的Fragment变成了androidx.fragment.app包下,原有的代码下会画红线,Android Studio也会警告你出现错误,可是不用担忧,依然能够正常编译,Android Studio在编译的时候会自动完成基类的替换,但前提是你要确保你项目里的gradle.properties进行了以下设置。
android.useAndroidX=true
android.enableJetifier=true
复制代码
为了消除这些难看的红线,你能够直接将新的Fragment使用这种方式强制转换成原有的Fragment。
TextureSupportMapFragment mapFragment = TextureSupportMapFragment
.class.cast(getChildFragmentManager()
.findFragmentById(R.id.map_view));
复制代码
同理,也能够将旧的Fragment强制类型转换成新的Fragment.
Fragment f = Fragment.class.cast(mapFragment);
复制代码
(注:上面的TextureSupportMapFragment是一个典型案例,他是高德地图SDK中的Fragment,它自己已经继承了v4包下的Fragment,能够用过上面的转换来使他兼容AndroidX)
最后补充一个小Tips:当咱们在使用Fragment#getActivity()时返回的是一个可空值,若是没有判空检查在Android Studio中将会出现一个恶心的黄色警告,你可使用requireActivity()来代替它,一样的方法还有requireFragmentManager()等.
Fragment拥有Activity全部的生命周期回调函数而且因为自身特色还扩展了一些回调函数,若是不熟悉Fragment,很容易凭直觉形成误会.例如,一个Fragment并不会由于在Fragment回退栈上有其余Fragment把它盖住,又或者是你使用FragmentTransition将它hide而致使他onPause,onPause只跟此Fragment依附的Activity有关,这在Fragment的源码中写得清清楚楚.
/**
* Called when the Fragment is no longer resumed. This is generally
* tied to {@link Activity#onPause() Activity.onPause} of the containing
* Activity's lifecycle. */ @CallSuper public void onPause() { mCalled = true; } 复制代码
那当咱们想在Fragment不显示时作一些事情要怎么办呢?咱们有onHiddenChanged回调,当Fragment的显示状态经过FragmentTransition改变时(hide和show),就会回调这个函数,参数hidden将告诉你这个Fragment如今是被隐藏仍是显示着.
/**
* Called when the hidden state (as returned by {@link #isHidden()} of
* the fragment has changed. Fragments start out not hidden; this will
* be called whenever the fragment changes state from that.
* @param hidden True if the fragment is now hidden, false otherwise.
*/
public void onHiddenChanged(boolean hidden) {
}
复制代码
经常使用的回调有这些:
onInflate(Context,AttributeSet,Bundle)只有硬编码在xml中的Fragment(即便用fragment标签)才会回调此方法,这与自定义View十分相似,在实例化xml布局时该方法会被调用,先于onAttach.
onAttach(Context)执行该方法时,Fragment与Activity已经完成绑定,当一个Fragment被添加到FragmentManager时,若是不是在xml中直接定义fragment标签,那么该方法老是最早被回调.该方法传入一个Context对象,实际上就是该Fragment依附的Activity.重写该方法时记得要调用父类的super.onAttach,父类的onAttach调用返回后,此时调用getActivity将不会返回null,可是Activity#onCreate可能还有没有执行完毕(若是是在xml中定义,这种状况就会发生,由于此时这个回调的这个发生的时间也就是你在Activity#onCreate里setContentView的时间,直到Fragment#onViewCreated返回以后,Activity#onCreate才会继续执行)。
onCreate(Bundle)用来初始化Fragment。它老是在onAttach执行完毕后回调,可经过参数savedInstanceState获取以前保存的值,记得必定要调用父类的super.onCreate。
onCreateView(LayoutInflater,ViewGroup,Bundle)须要返回一个View用来初始化Fragment的布局,它老是在onCreate执行完毕后回调。默认返回null,值得注意的是,若返回null Fragment#onViewCreated将会被跳过,且若是是在xml中定义fragment标签并用name指定某个Fragment,则这个方法不容许返回null,不然就会报错。当使用ViewPager+Fragment时此方法可能会被屡次调用(与Fragment#onDestroyView成对调用)。
onActivityCreated(Bundle)执行该方法时,与Fragment绑定的Activity的onCreate方法已经执行完成并返回,若在此方法以前与Activity交互交互没有任何保证,引用了未初始化的资源就会应发空指针异常。
onStart()执行该方法时,Fragment所在的Activity由不可见变为可见状态
onResume()执行该方法时,Fragment所在的Activity处于活动状态,用户可与之交互.
onPause()执行该方法时,Fragment所在的Activity处于暂停状态,但依然可见,用户不能与之交互,好比Dialog盖住了Activity
onStop()执行该方法时,Fragment所在的Activity彻底不可见
onSaveInstanceState(Bundle)保存当前Fragment的状态。该方法会自动保存Fragment的状态,好比EditText键入的文本,即便Fragment被回收又从新建立,同样能恢复EditText以前键入的文本,说实话我不太喜欢这个方法,保存到Bundle里的设计实在是太蠢了,不过好在如今已经有了代替它的方案,Google的Android Jetpack MVVM框架,以后我也会专门出一篇文章来介绍。
onDestroyView()销毁与Fragment有关的视图,但未与Activity解除绑定,通常在这个回调里解除Fragment对视图的引用。一般在ViewPager+Fragment的方式下会使用并重写此方法,而且与Fragment#onCreateView同样多是屡次的。
onDestroy()销毁Fragment。一般按Back键退出或者Fragment被移除FragmentManager时调用此方法,此时应该清理Fragment中所管理的全部数据,它会在onDetach以前回调。
onDetach()解除与Activity的绑定。在onDestroy方法以后调用。Fragment生命周期的最末期,若在super.onDetach返回后getActivity(),你将会获得一个null。
使用 FragmentManager 执行的操做包括:
public class FragmentActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
ExampleFragment fragment = new ExampleFragment();
// 建立参数
Bundle bundle = new Bundle();
bundle.putString("argKey", "value");
fragment.setArguments(bundle);
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
// 略...
fragment.apiFuncation();
}
}
public static class ExampleFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 获取
Bundle bundle = getArguments();
String arg = bundle.getString("argKey");
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
复制代码
在Fragment能够经过getActivity()来获取Fragment所依附的Activity实例,Activity也能够经过 findFragmentById() 或 findFragmentByTag()来获取对应的Fragment。
使用getSupportFragmentManager()方法获取FragmentManager,当前Activity就必须继承于FragmentActivity以及其子类。
// FragmentActivity类:
final FragmentController mFragments = FragmentController.createController(new FragmentActivity.HostCallbacks());
public FragmentManager getSupportFragmentManager() {
return this.mFragments.getSupportFragmentManager();
}
// 内部类
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
public HostCallbacks() {
super(FragmentActivity.this);
}
......
}
// FragmentController类:
private final FragmentHostCallback<?> mHost;
public static FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback<?> callbacks) {
this.mHost = callbacks;
}
public FragmentManager getSupportFragmentManager() {
return this.mHost.getFragmentManagerImpl();
}
// FragmentHostCallback类:
FragmentHostCallback(@NonNull FragmentActivity activity) {
// 关注一下第三个参数activity.mHandler
this(activity, activity, activity.mHandler, 0);
}
FragmentHostCallback(@Nullable Activity activity, @NonNull Context context, @NonNull Handler handler, int windowAnimations) {
// 初始化了FragmentManagerImpl类
this.mFragmentManager = new FragmentManagerImpl();
this.mActivity = activity;
this.mContext = (Context)Preconditions.checkNotNull(context, "context == null");
// 初始化了Handler,该mHandler会在commit操做中用到
this.mHandler = (Handler)Preconditions.checkNotNull(handler, "handler == null");
this.mWindowAnimations = windowAnimations;
}
FragmentManagerImpl getFragmentManagerImpl() {
return this.mFragmentManager;
}
// FragmentManagerImpl类:
final class FragmentManagerImpl extends FragmentManager implements Factory2
复制代码
咱们能够很清晰的看到mFragments被final修饰并且又是类成员,所以一个FragmentActivity对应一个FragmentController、一个FragmentHostCallback和一个FragmentManagerImpl。
// FragmentManagerImpl类:
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
// BackStackRecord类:
final class BackStackRecord extends FragmentTransaction
implements BackStackEntry, OpGenerator {
......
public BackStackRecord(FragmentManagerImpl manager) {
this.mManager = manager;
}
...
}
复制代码
其实就是返回了继承于FragmentTransaction的BackStackRecord类。注意啦BackStackRecord类很重要,很是重要。本文以android-28为标准而讲解,而本类在28中修改很大,28以前的版本BackStackRecord实现了Runnable接口,具体的可自行查看。该类直译过来可被称为:返回堆栈记录,此后的有关fragment的基本全部操做都是经过它来完成。
// BackStackRecord类:
ArrayList<BackStackRecord.Op> mOps = new ArrayList();
public FragmentTransaction add(Fragment fragment, @Nullable String tag) {
this.doAddOp(0, fragment, tag, 1);
return this;
}
private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
// 获取fragment的Class对象
Class fragmentClass = fragment.getClass();
// 获取该fragment对象的修饰符
int modifiers = fragmentClass.getModifiers();
// 如该fragment为:匿名类或者不是public修饰符标识的类或者(它是内部类且不是静态的)
if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers) || fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)) {
// 则抛出以下异常
throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName() + " must be a public static class to be properly recreated from" + " instance state.");
} else {
fragment.mFragmentManager = this.mManager;
if (tag != null) {
// 防止同一个fragment被add屡次而且设置了多个不一样的tag
// 若是tag不等于空,而且tag不等于fragment.mTag
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
// 则抛出以下异常
throw new IllegalStateException("Can't change tag of fragment " + fragment + ": was " + fragment.mTag + " now " + tag);
}
fragment.mTag = tag;
}
if (containerViewId != 0) {
// 容器视图id,即FrameLayout布局id
if (containerViewId == -1) {
throw new IllegalArgumentException("Can't add fragment " + fragment + " with tag " + tag + " to container view with no id");
}
// 方法屡次add其containerViewId且设置多个不一样的containerViewId
if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
throw new IllegalStateException("Can't change container ID of fragment " + fragment + ": was " + fragment.mFragmentId + " now " + containerViewId);
}
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
this.addOp(new BackStackRecord.Op(opcmd, fragment));
}
}
void addOp(BackStackRecord.Op op) {
this.mOps.add(op);
op.enterAnim = this.mEnterAnim;
op.exitAnim = this.mExitAnim;
op.popEnterAnim = this.mPopEnterAnim;
op.popExitAnim = this.mPopExitAnim;
}
// BackStackRecord内部类Op:
static final class Op {
int cmd;//指令:表明对fragment的操做,好比:add==1
Fragment fragment;//保存要操做的fragment
// 如下四个为动画设置
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
Op() {
}
Op(int cmd, Fragment fragment) {
this.cmd = cmd;
this.fragment = fragment;
}
}
复制代码
再次将此部分有关代码放到了一块儿,接着一步一步说明一下吧:
// BackStackRecord类:
public FragmentTransaction show(Fragment fragment) {
this.addOp(new BackStackRecord.Op(5, fragment));
return this;
}
复制代码
show操做其实只是调用addOp(new BackStackRecord.Op(5, fragment))方法,设置一下Op类的cmd指令。
// BackStackRecord类:
public int commit() {
return this.commitInternal(false); // 注意这个false哦
}
int commitInternal(boolean allowStateLoss) {
// 若重复commit,则会抛出此异常
if (this.mCommitted) {
throw new IllegalStateException("commit already called");
} else {
if (FragmentManagerImpl.DEBUG) {
Log.v("FragmentManager", "Commit: " + this);
LogWriter logw = new LogWriter("FragmentManager");
PrintWriter pw = new PrintWriter(logw);
this.dump(" ", (FileDescriptor)null, pw, (String[])null);
pw.close();
}
this.mCommitted = true;
// 这个成员默认是false,只有咱们本身调用了addToBackStack方法,才会设置为true
if (this.mAddToBackStack) {
this.mIndex = this.mManager.allocBackStackIndex(this);
} else {
this.mIndex = -1;
}
// 此mManager咱们上面第一部分讲解过,实际为FragmentManagerImpl类
this.mManager.enqueueAction(this, allowStateLoss);
return this.mIndex;
}
}
// FragmentManagerImpl类:
// 注意:参数action为BackStackRecord类,而allowStateLoss为false,上面有说明
public void enqueueAction(FragmentManagerImpl.OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
// 状态丢失的异常检查(具体请参考:https://www.jianshu.com/p/aa735c60c867)
// 若是咱们提交使用的是commit方法,则会走到该判断里来,由于commit方法allowStateLoss传的是false。若是咱们提交使用的是commitAllowingStateLoss方法,则不会走到该判断中来,由于commitAllowingStateLoss方法传入的allowStateLoss为true
this.checkStateLoss();
}
synchronized(this) {
if (!this.mDestroyed && this.mHost != null) {
if (this.mPendingActions == null) {
this.mPendingActions = new ArrayList();
}
// 加入待定任务队列中,mPendingActions是ArrayList
this.mPendingActions.add(action);
this.scheduleCommit();
} else if (!allowStateLoss) {
throw new IllegalStateException("Activity has been destroyed");
}
}
}
void scheduleCommit() {
synchronized(this) {
boolean postponeReady = this.mPostponedTransactions != null && !this.mPostponedTransactions.isEmpty();
boolean pendingReady = this.mPendingActions != null && this.mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
this.mHost.getHandler().removeCallbacks(this.mExecCommit);
this.mHost.getHandler().post(this.mExecCommit);
}
}
}
复制代码
从上面的三步中咱们了解到了,如今逻辑以及到了mExecCommit(Runnable)的run方法里,咱们先不急看run()方法,咱们回来看一下enqueueAction()方法为何把action添加进入mPendingActions里?由于从后面的代码中能够了解每次commit后都会将mPendingActions集合清空,那为何还要使用集合保存呢?不知作别的小伙伴有没有这方面的纠结,我一开始反正是纠结的。那咱们来分析一下使用mPendingActions的缘由:咱们知道了commit的后续操做是在mExecCommit(Runnable)的run方法里,而mExecCommit又是经过Handler看成消息post出去的,所以这里就能够把commit操做看成是在异步中执行的逻辑。这又是什么缘由呢?那是由于Handler发出去的消息并非被Looper立刻执行的,而是须要先从消息队列中取出来再去执行,所以在这个空隙,咱们能够会屡次切换fragment(场景:app的首页是由底部多个Tab+多个fragmnet实现,咱们频繁屡次切换tab)而致使屡次生成action,所以须要一个集合来看成队列将多个action添加进去,在后面统一处理。
这里咱们再说一下几种提交操做的方法:
用commit()提交有时候会遇到IllegalStateException, 说你在onSaveInstanceState()以后提交, commit()和commitAllowingStateLoss()在实现上惟一的不一样就是当你调用commit()的时候, FragmentManger会检查是否已经存储了它本身的状态, 若是已经存了, 就抛出IllegalStateException。 那么若是你调用的是commitAllowingStateLoss(),则FragmentManger不会检查是否已经存储了它本身的状态(上面代码中已添加备注说明),而且要是在onSaveInstanceState()以后,你可能会丢失掉什么状态呢? 答案是你可能会丢掉FragmentManager的状态, 即save以后任何被添加或被移除的Fragments.
使用commit()的时候, 一旦调用, 这个commit并非当即执行的, 它会被发送到主线程的任务队列当中去, 当主线程准备好执行它的时候执行. popBackStack()的工做也是这样, 发送到主线程任务队列中去. 也即说它们都是异步的.可是有时候你但愿你的操做是当即执行的,以前的开发者会在commit()调用以后加上 executePendingTransactions()来保证当即执行, 即变异步为同步.support library从v24.0.0开始提供了 commitNow()方法,以前用executePendingTransactions()会将全部pending在队列中还有你新提交的transactions都执行了, 而commitNow()将只会执行你当前要提交的transaction. 因此commitNow()避免你会不当心执行了那些你可能并不想执行的transactions.
可是你不能对要加在back stack中的transaction使用commitNow(),即addToBackStack()和commitNow()不能同时使用.为何呢? 想一想一下, 若是你有一个提交使用了commit(), 紧接着又有另外一个提交使用了commitNow(), 两个都想加入back stack, 那back stack会变成什么样呢? 究竟是哪一个transaction在上, 哪一个在下? 答案将是一种不肯定的状态, 由于系统并无提供任何保证来确保顺序, 因此系统决定干脆不支持这个操做.前面提过popBackStack()是异步的, 因此它一样也有一个同步的兄弟popBackStackImmediate().因此实际应用的时候怎么选择呢? 1.若是你须要同步的操做, 而且你不须要加到back stack里, 使用commitNow(). support library在FragmentPagerAdapter里就使用了commitNow()来保证在更新结束的时候, 正确的页面被加上或移除. 2.若是你操做不少transactions, 而且不须要同步, 或者你须要把transactions加在back stack里, 那就使用commit(). 3.若是你但愿在某一个指定的点, 确保全部的transactions都被执行, 那么使用executePendingTransactions().
好啦,咱们能够继续分析接下的啦(mExecCommit(Runnable)的run方法):
// FragmentManagerImpl类:
Runnable mExecCommit = new Runnable() {
public void run() {
FragmentManagerImpl.this.execPendingActions();
}
};
public boolean execPendingActions() {
this.ensureExecReady(true);
boolean didSomething;
// mTmpRecords:临时存储全部待执行的动做(mPendingActions)生成的 BackStackRecord
// mTmpIsPop:存储 BackStackRecord 是否为出栈。
for(didSomething = false; this.generateOpsForPendingActions(this.mTmpRecords, this.mTmpIsPop); didSomething = true) {
this.mExecutingActions = true;
try {
this.removeRedundantOperationsAndExecute(this.mTmpRecords, this.mTmpIsPop);
} finally {
this.cleanupExec();
}
}
this.doPendingDeferredStart();
this.burpActive();
return didSomething;
}
// 遍历 mPendingActions 调用 OpGenerator.generateOps() 方法生成 BackStackRecord 添加到 mTmpRecords 并把是否为出栈添加到 mTmpIsPop 中
private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records, ArrayList<Boolean> isPop) {
boolean didSomething = false;
synchronized(this) {
if (this.mPendingActions != null && this.mPendingActions.size() != 0) {
int numActions = this.mPendingActions.size();
for(int i = 0; i < numActions; ++i) {
didSomething |= ((FragmentManagerImpl.OpGenerator)this.mPendingActions.get(i)).generateOps(records, isPop);
}
// 清空待定任务队列
this.mPendingActions.clear();
this.mHost.getHandler().removeCallbacks(this.mExecCommit);
return didSomething;
} else {
return false;
}
}
}
// BackStackRecord类
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (FragmentManagerImpl.DEBUG) {
Log.v("FragmentManager", "Run: " + this);
}
records.add(this);
// 添加false
isRecordPop.add(false);
if (this.mAddToBackStack) {
// 添加到“回退栈”中
this.mManager.addBackStackState(this);
}
return true;
}
// FragmentManagerImpl类的内部类PopBackStackState:
private class PopBackStackState implements FragmentManagerImpl.OpGenerator {
...
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
...
return FragmentManagerImpl.this.popBackStackState(records, isRecordPop, this.mName, this.mId, this.mFlags);
}
}
// FragmentManagerImpl类:
boolean popBackStackState(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, String name, int id, int flags) {
if (this.mBackStack == null) {
return false;
} else {
int index;
if (name == null && id < 0 && (flags & 1) == 0) {
...
records.add(this.mBackStack.remove(index));
// 添加true
isRecordPop.add(true);
} else {
...
for(int i = this.mBackStack.size() - 1; i > index; --i) {
records.add(this.mBackStack.remove(i));
// 添加true
isRecordPop.add(true);
}
}
return true;
}
}
void addBackStackState(BackStackRecord state) {
if (this.mBackStack == null) {
this.mBackStack = new ArrayList();
}
// “回退栈” == mBackStack(ArrayList<BackStackRecord>)
this.mBackStack.add(state);
}
复制代码
在 Runnable 中执行 execPendingActions() 方法,该方法分为几点来分析:
经过generateOpsForPendingActions方法遍历 mPendingActions 调用 OpGenerator.generateOps() 方法设置了 mTmpRecords(临时存储全部待执行的动做:BackStackRecord) 和 mTmpIsPop (存储 BackStackRecord 是否为出栈) OpGenerator.generateOps()方法,上面曾提起过OpGenerator接口会有两个地方实现,而BackStackRecord类实现OpGenerator接口中的generateOps()方法上面代码给出了源码,其实就是设置this自身添加到records(即mTmpRecords)集合中,并同时添加一个false到isRecordPop(即mTmpIsPop)集合里表示此动做不是“回退栈”的出栈操做。而另外一个实现OpGenerator接口的generateOps()方法里isRecordPop(即mTmpIsPop)集合内添加的是true(源码已展现)
咱们接着往下走removeRedundantOperationsAndExecute():
// FragmentManagerImpl类:
private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (records != null && !records.isEmpty()) {
if (isRecordPop != null && records.size() == isRecordPop.size()) {
this.executePostponedTransaction(records, isRecordPop);
int numRecords = records.size();
int startIndex = 0;
for(int recordNum = 0; recordNum < numRecords; ++recordNum) {
boolean canReorder = ((BackStackRecord)records.get(recordNum)).mReorderingAllowed;
if (!canReorder) {
if (startIndex != recordNum) {
this.executeOpsTogether(records, isRecordPop, startIndex, recordNum);
}
int reorderingEnd = recordNum + 1;
// 根据上面的分析,只有“回退栈”执行出栈才会执行此处代码
if ((Boolean)isRecordPop.get(recordNum)) {
while(reorderingEnd < numRecords && (Boolean)isRecordPop.get(reorderingEnd) && !((BackStackRecord)records.get(reorderingEnd)).mReorderingAllowed) {
++reorderingEnd;
}
}
this.executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
startIndex = reorderingEnd;
recordNum = reorderingEnd - 1;
}
}
if (startIndex != numRecords) {
this.executeOpsTogether(records, isRecordPop, startIndex, numRecords);
}
} else {
throw new IllegalStateException("Internal error with the back stack records");
}
}
}
private void executeOpsTogether(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
boolean allowReordering = ((BackStackRecord)records.get(startIndex)).mReorderingAllowed;
boolean addToBackStack = false;
if (this.mTmpAddedFragments == null) {
this.mTmpAddedFragments = new ArrayList();
} else {
this.mTmpAddedFragments.clear();
}
this.mTmpAddedFragments.addAll(this.mAdded);
Fragment oldPrimaryNav = this.getPrimaryNavigationFragment();
int postponeIndex;
for(postponeIndex = startIndex; postponeIndex < endIndex; ++postponeIndex) {
BackStackRecord record = (BackStackRecord)records.get(postponeIndex);
boolean isPop = (Boolean)isRecordPop.get(postponeIndex);
// 对mOps进行优化,add或者remove(mOps即第三部分提到的保存add进的fragmnet集合)
if (!isPop) {
// 在28以前这里会执行 expandReplaceOps 方法把 replace 替换(目标 fragment 已经被 add )成相应的 remove 和 add 两个操做,或者(目标 fragment 没有被 add )只替换成 add 操做。
oldPrimaryNav = record.expandOps(this.mTmpAddedFragments, oldPrimaryNav);
} else {
oldPrimaryNav = record.trackAddedFragmentsInPop(this.mTmpAddedFragments, oldPrimaryNav);
}
addToBackStack = addToBackStack || record.mAddToBackStack;
}
this.mTmpAddedFragments.clear();
if (!allowReordering) {
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex, false);
}
// 若是allowReordering为true,则此方法后面会走不通,则会走下面的判断,最终都会到达咱们这部分最重要的方法————moveToState
executeOps(records, isRecordPop, startIndex, endIndex);
postponeIndex = endIndex;
if (allowReordering) {
/**
* allowReordering为true,走此逻辑
* 容许从新排序(须要本身调用FragmentTransaction.setReorderingAllowed()方法设置)
* 必须启用fragment事务中的从新排序(即allowReordering),才能
* 使延迟的fragment过渡生效,具体用法请参考:https://www.jianshu.com/p/232073710172
*/
ArraySet<Fragment> addedFragments = new ArraySet();
this.addAddedFragments(addedFragments);
// 此方法最后会走到moveToState方法,具体源码请自行查看
postponeIndex = this.postponePostponableTransactions(records, isRecordPop, startIndex, endIndex, addedFragments);
this.makeRemovedFragmentsInvisible(addedFragments);
}
...
}
private static void executeOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
for(int i = startIndex; i < endIndex; ++i) {
BackStackRecord record = (BackStackRecord)records.get(i);
boolean isPop = (Boolean)isRecordPop.get(i);
// 从上面分析可知isRecordPop取出来的是false(“回退栈”出栈时为true)
if (isPop) {
record.bumpBackStackNesting(-1);
boolean moveToState = i == endIndex - 1;
// 若为回退栈出栈操做,则执行此方法,
// 此方法中根据op.cmd判断对framgnet进行相应的处理,
// 与else分支相同的cmd指令处理逻辑不一样
record.executePopOps(moveToState);
} else {
record.bumpBackStackNesting(1);
record.executeOps();
}
}
}
复制代码
咱们从removeRedundantOperationsAndExecute()方法的源码中能够看到该方法其实是对records集合中全部动做的startIndex(起始动做位置), recordNum(须要操做的动做个数)的设置,而后都会去调用executeOpsTogether()方法,而executeOpsTogether()方法咱们只展现部分代码,其中会对mOps进行扩展操做,最后调用方法executeOps()继续操做,而方法executeOps中又通过判断最终调用BackStackRecord类的executeOps()方法。
// BackStackRecord类:
void executeOps() {
int numOps = this.mOps.size();
// 遍历执行全部的mOps(包含咱们commit操做前的全部其它操做,好比:add、hide等)
for(int opNum = 0; opNum < numOps; ++opNum) {
BackStackRecord.Op op = (BackStackRecord.Op)this.mOps.get(opNum);
Fragment f = op.fragment;
if (f != null) {
f.setNextTransition(this.mTransition, this.mTransitionStyle);
}
// 根据op.cmd指令进行操做,相信根据下面每一个分支的逻辑能分别出每一个指令对应的操做
switch(op.cmd) {
case 1:
f.setNextAnim(op.enterAnim);
this.mManager.addFragment(f, false);
break;
case 2:
default:
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
case 3:
f.setNextAnim(op.exitAnim);
this.mManager.removeFragment(f);
break;
case 4:
f.setNextAnim(op.exitAnim);
this.mManager.hideFragment(f);
break;
case 5:
f.setNextAnim(op.enterAnim);
this.mManager.showFragment(f);
break;
case 6:
f.setNextAnim(op.exitAnim);
this.mManager.detachFragment(f);
break;
case 7:
f.setNextAnim(op.enterAnim);
this.mManager.attachFragment(f);
break;
case 8:
this.mManager.setPrimaryNavigationFragment(f);
break;
case 9:
this.mManager.setPrimaryNavigationFragment((Fragment)null);
}
if (!this.mReorderingAllowed && op.cmd != 1 && f != null) {
this.mManager.moveFragmentToExpectedState(f);
}
}
// 只有没设置setReorderingAllowed(true)的才能继续,
// 而设置的会在前面的某步逻辑当中走到moveToState方法内,上面有说明
if (!this.mReorderingAllowed) {
// 最后调用咱们这部分最重要的方法:moveToState
this.mManager.moveToState(this.mManager.mCurState, true);
}
}
// 1. 提交add操做时将当前提交的fragmen添加进mActive和mAdded里
// 并重置fragment.mAdded和fragment.mRemoving两个的状态
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (DEBUG) {
Log.v("FragmentManager", "add: " + fragment);
}
// 调用makeActive,将fragment添加进mActive
this.makeActive(fragment);
if (!fragment.mDetached) {
if (this.mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
synchronized(this.mAdded) {
// 将fragment也添加进mAdded里
this.mAdded.add(fragment);
}
// 设置mAdded和mRemoving状态
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mView == null) {
fragment.mHiddenChanged = false;
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
this.mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
this.moveToState(fragment);
}
}
}
void makeActive(Fragment f) {
if (f.mIndex < 0) {
f.setIndex(this.mNextFragmentIndex++, this.mParent);
if (this.mActive == null) {
this.mActive = new SparseArray();
}
// 将fragment添加进mActive
this.mActive.put(f.mIndex, f);
if (DEBUG) {
Log.v("FragmentManager", "Allocated fragment index " + f);
}
}
}
// 2. 提交remove操做时将当前提交的fragment从mAdded移除
// 并重置fragment.mAdded和fragment.mRemoving两个的状态
public void removeFragment(Fragment fragment) {
if (DEBUG) {
Log.v("FragmentManager", "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
}
boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
synchronized(this.mAdded) {
this.mAdded.remove(fragment);
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
this.mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
fragment.mRemoving = true;
}
}
// 3. 设置fragment.mHidden的状态为false
public void showFragment(Fragment fragment) {
if (DEBUG) {
Log.v("FragmentManager", "show: " + fragment);
}
if (fragment.mHidden) {
fragment.mHidden = false;
fragment.mHiddenChanged = !fragment.mHiddenChanged;
}
}
// 4. 设置fragment.mHidden的状态为true
public void hideFragment(Fragment fragment) {
if (DEBUG) {
Log.v("FragmentManager", "hide: " + fragment);
}
if (!fragment.mHidden) {
fragment.mHidden = true;
fragment.mHiddenChanged = !fragment.mHiddenChanged;
}
}
复制代码
咱们从executeOps()方法中能够看到该方法里经过for循环对mOps进行了遍历,而这次遍历会对咱们本次commit提交的全部操做进行设置。好比咱们上面列出的四中操做:add、remove、show和hide同样。
咱们先来看这段代码中的两个集合:mAdded和mActive
mAdded:包含了全部已经 added 而且没有被从Activity中removed和detached的Fragments 注:若是一个 Fragment被添加到Activity中那么这个Fragment会被added到该列表。Fragment被从Activity中removed或者Fragment从Activity中detached,则就会被从该列表中移除。
mAdded 的一个超集,是绑定到一个 Activity 上的全部 Fragment。包括返回栈中全部的经过任何 FragmentTransaction 添加的 Fragments。这是很是重要的由于以下缘由:
当一个 Activity 要保存它的 State 时,它必须保存它全部 Fragment 的状态,由于 mActive 保存了全部 Fragment,因此系统只要存储这个列表里的 Fragment 的状态就行了。而mAdded 只是被序列化成一个整形数组,每一个元素指向 Fragment 在 mActive 中的下标位置(这块在前面 Fragment 的存储与恢复中分析到了)。
在恢复 Activity 的状态时,FragmentManager 的状态也会被恢复,mActive 列表就能够被用来恢复 mAdded 列表,由于保存状态的时候mAdded 被简单的保存为整形数组。
当一个 Activity 经历它的各生命周期时,它必须引发全部绑定的 Fragment 经历各自的生命周期。
该 Activity 的 FragmentManager 有义务去引导全部 Fragemnt 转换到正确的状态,这其中包括屏幕上可见的 Fragment 的 View 层级的初始化,而且调用正确的生命周期函数。
为了确保完整,FragmentManager 将遍历mActive 中全部的 Fragment,而不只仅是 mAdded。
它持有全部 BackStack 返回栈引用的对象。
这确保了返回栈中对 Fragment 操做的回滚可以实现。
注:若是一个Fragment被添加到Activity中那么这个Fragment会被added到该列表。只有在两种状况 Fragment才会被从该列表中移除:一是,Fragment被从Activity中移除而且没有在返回栈中;二是一个transaction从返回栈中被pop出来、Fragment的add或者replace操做被逆向,即返回栈再也不持有 Fragment。
咱们接着来讲moveToState这个方法:
// FragmentManagerImpl类:
void moveToState(int newState, boolean always) {
if (this.mHost == null && newState != 0) {
throw new IllegalStateException("No activity");
} else if (always || newState != this.mCurState) {
this.mCurState = newState;
if (this.mActive != null) {
int numAdded = this.mAdded.size();
int numActive;
// 遍历mAdded集合,确定会走此代码逻辑
for(numActive = 0; numActive < numAdded; ++numActive) {
Fragment f = (Fragment)this.mAdded.get(numActive);
// 将fragment移至预期状态
this.moveFragmentToExpectedState(f);
}
numActive = this.mActive.size();
// // 遍历mActive集合(若调用回退栈出栈,则会走此出代码)
for(int i = 0; i < numActive; ++i) {
Fragment f = (Fragment)this.mActive.valueAt(i);
// 当前framgnet不为空 而且 此时操做为remove或者detach 而且不是新添加的则会执行下面代码
if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
// // 将fragment移至预期状态
this.moveFragmentToExpectedState(f);
}
}
// fragment的成员属性f.mDeferStart为true才能走通下面代码(具体暂不分析)
this.startPendingDeferredFragments();
if (this.mNeedMenuInvalidate && this.mHost != null && this.mCurState == 4) {
this.mHost.onSupportInvalidateOptionsMenu();
this.mNeedMenuInvalidate = false;
}
}
}
}
复制代码
咱们来看一下moveToState方法中的参数newState,BackStackRecord类中的executeOps里传过来的是mManager.mCurState,而mManager.mCurState默认为0,即须要add的状态。咱们如今回想一下fragment为何会随着Activity的周期变化而变化呢?咱们来看段代码:
// FragmentActivity类:
protected void onCreate(@Nullable Bundle savedInstanceState) {
this.mFragments.attachHost((Fragment)null);
super.onCreate(savedInstanceState);
......
this.mFragments.dispatchCreate();
}
// FragmentController类:
public void dispatchCreate() {
this.mHost.mFragmentManager.dispatchCreate();
}
// FragmentManagerImpl类:
public void dispatchCreate() {
this.mStateSaved = false;
this.mStopped = false;
this.dispatchStateChange(1);
}
private void dispatchStateChange(int nextState) {
try {
this.mExecutingActions = true;
// 这里走到了moveToState
this.moveToState(nextState, false);
} finally {
this.mExecutingActions = false;
}
this.execPendingActions();
}
复制代码
这段代码是从上到下的顺序执行的,咱们能够看到在FragmentActivity的onCreate周期方法中一步一步的走到了moveToState,而moveToState正是走到fragment周期方法的关键(FragmentActivity的其它周期方法同onCreate方法也会走到对应的fragment的周期方法中)。既然moveToState是走到fragment周期方法的关键,那咱们继续往下分析,上面已经说到会走到FragmentManagerImpl类的moveFragmentToExpectedState(f)方法中:
// FragmentManagerImpl类:
void moveFragmentToExpectedState(Fragment f) {
if (f != null) {
int nextState = this.mCurState;
if (f.mRemoving) {
// 若是操做为remove则nextState设置为1或者0,用于后面判断
if (f.isInBackStack()) {
nextState = Math.min(nextState, 1);
} else {
nextState = Math.min(nextState, 0);
}
}
// 继续走同名方法
this.moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
// 若是当前View不为空,则添加布局执行动画
if (f.mView != null) {
Fragment underFragment = this.findFragmentUnder(f);
if (underFragment != null) {
View underView = underFragment.mView;
ViewGroup container = f.mContainer;
int underIndex = container.indexOfChild(underView);
int viewIndex = container.indexOfChild(f.mView);
if (viewIndex < underIndex) {
container.removeViewAt(viewIndex);
container.addView(f.mView, underIndex);
}
}
if (f.mIsNewlyAdded && f.mContainer != null) {
if (f.mPostponedAlpha > 0.0F) {
f.mView.setAlpha(f.mPostponedAlpha);
}
f.mPostponedAlpha = 0.0F;
f.mIsNewlyAdded = false;
FragmentManagerImpl.AnimationOrAnimator anim = this.loadAnimation(f, f.getNextTransition(), true, f.getNextTransitionStyle());
if (anim != null) {
setHWLayerAnimListenerIfAlpha(f.mView, anim);
if (anim.animation != null) {
f.mView.startAnimation(anim.animation);
} else {
anim.animator.setTarget(f.mView);
anim.animator.start();
}
}
}
}
if (f.mHiddenChanged) {
// 完成显示隐藏fragment
this.completeShowHideFragment(f);
}
}
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) {
// 从新判断设置newState状态值
if ((!f.mAdded || f.mDetached) && newState > 1) {
newState = 1;
}
if (f.mRemoving && newState > f.mState) {
if (f.mState == 0 && f.isInBackStack()) {
newState = 1;
} else {
newState = f.mState;
}
}
if (f.mDeferStart && f.mState < 3 && newState > 2) {
newState = 2;
}
// 若是fragment自身的状态<=newState状态,则证实此时fragment是被建立阶段
if (f.mState <= newState) {
label297: {
if (f.mFromLayout && !f.mInLayout) {
return;
}
if (f.getAnimatingAway() != null || f.getAnimator() != null) {
f.setAnimatingAway((View)null);
f.setAnimator((Animator)null);
this.moveToState(f, f.getStateAfterAnimating(), 0, 0, true);
}
// 判断fragment状态进行处理
switch(f.mState) {
case 0:
if (newState > 0) {
if (DEBUG) {
Log.v("FragmentManager", "moveto CREATED: " + f);
}
if (f.mSavedFragmentState != null) {
f.mSavedFragmentState.setClassLoader(this.mHost.getContext().getClassLoader());
f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray("android:view_state");
f.mTarget = this.getFragment(f.mSavedFragmentState, "android:target_state");
if (f.mTarget != null) {
f.mTargetRequestCode = f.mSavedFragmentState.getInt("android:target_req_state", 0);
}
if (f.mSavedUserVisibleHint != null) {
f.mUserVisibleHint = f.mSavedUserVisibleHint;
f.mSavedUserVisibleHint = null;
} else {
f.mUserVisibleHint = f.mSavedFragmentState.getBoolean("android:user_visible_hint", true);
}
if (!f.mUserVisibleHint) {
f.mDeferStart = true;
if (newState > 2) {
newState = 2;
}
}
}
f.mHost = this.mHost;
f.mParentFragment = this.mParent;
f.mFragmentManager = this.mParent != null ? this.mParent.mChildFragmentManager : this.mHost.getFragmentManagerImpl();
if (f.mTarget != null) {
if (this.mActive.get(f.mTarget.mIndex) != f.mTarget) {
throw new IllegalStateException("Fragment " + f + " declared target fragment " + f.mTarget + " that does not belong to this FragmentManager!");
}
if (f.mTarget.mState < 1) {
this.moveToState(f.mTarget, 1, 0, 0, true);
}
}
this.dispatchOnFragmentPreAttached(f, this.mHost.getContext(), false);
f.mCalled = false;
// 执行fragment的onAttach周期方法
f.onAttach(this.mHost.getContext());
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
this.mHost.onAttachFragment(f);
} else {
f.mParentFragment.onAttachFragment(f);
}
this.dispatchOnFragmentAttached(f, this.mHost.getContext(), false);
if (!f.mIsCreated) {
this.dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
f.performCreate(f.mSavedFragmentState);
this.dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState);
f.mState = 1;
}
f.mRetaining = false;
}
case 1:
this.ensureInflatedFragmentView(f);
if (newState > 1) {
if (DEBUG) {
Log.v("FragmentManager", "moveto ACTIVITY_CREATED: " + f);
}
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
if (f.mContainerId == -1) {
this.throwException(new IllegalArgumentException("Cannot create fragment " + f + " for a container view with no id"));
}
container = (ViewGroup)this.mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
String resName;
try {
resName = f.getResources().getResourceName(f.mContainerId);
} catch (NotFoundException var9) {
resName = "unknown";
}
this.throwException(new IllegalArgumentException("No view found for id 0x" + Integer.toHexString(f.mContainerId) + " (" + resName + ") for fragment " + f));
}
}
f.mContainer = container;
// 执行fragment的onCreateView周期方法 f.performCreateView(f.performGetLayoutInflater(f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView == null) {
f.mInnerView = null;
} else {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
container.addView(f.mView);
}
if (f.mHidden) {
f.mView.setVisibility(8);
}
// 执行fragment的onViewCreated周期方法
f.onViewCreated(f.mView, f.mSavedFragmentState);
this.dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
f.mIsNewlyAdded = f.mView.getVisibility() == 0 && f.mContainer != null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
this.dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
// 执行fragment的onActivityCreated周期方法
f.mSavedFragmentState = null;
}
case 2:
if (newState > 2) {
if (DEBUG) {
Log.v("FragmentManager", "moveto STARTED: " + f);
}
// 执行framgnet的onStart周期方法
f.performStart();
this.dispatchOnFragmentStarted(f, false);
}
case 3:
break;
default:
break label297;
}
if (newState > 3) {
if (DEBUG) {
Log.v("FragmentManager", "moveto RESUMED: " + f);
}
// 执行framgnet的onResume周期方法
f.performResume();
this.dispatchOnFragmentResumed(f, false);
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
// 若是fragment自身的状态>=newState状态,则证实此时fragment是被销毁阶段
} else if (f.mState > newState) {
switch(f.mState) {
case 4:
if (newState < 4) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom RESUMED: " + f);
}
// 执行framgnet的onPause周期方法
f.performPause();
this.dispatchOnFragmentPaused(f, false);
}
case 3:
if (newState < 3) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom STARTED: " + f);
}
// 执行framgnet的onStop周期方法
f.performStop();
this.dispatchOnFragmentStopped(f, false);
}
case 2:
if (newState < 2) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom ACTIVITY_CREATED: " + f);
}
if (f.mView != null && this.mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
this.saveFragmentViewState(f);
}
// 执行framgnet的onDestroyView周期方法
f.performDestroyView();
this.dispatchOnFragmentViewDestroyed(f, false);
if (f.mView != null && f.mContainer != null) {
f.mContainer.endViewTransition(f.mView);
f.mView.clearAnimation();
FragmentManagerImpl.AnimationOrAnimator anim = null;
if (this.mCurState > 0 && !this.mDestroyed && f.mView.getVisibility() == 0 && f.mPostponedAlpha >= 0.0F) {
anim = this.loadAnimation(f, transit, false, transitionStyle);
}
f.mPostponedAlpha = 0.0F;
if (anim != null) {
this.animateRemoveFragment(f, anim, newState);
}
f.mContainer.removeView(f.mView);
}
f.mContainer = null;
f.mView = null;
f.mViewLifecycleOwner = null;
f.mViewLifecycleOwnerLiveData.setValue((Object)null);
f.mInnerView = null;
f.mInLayout = false;
}
case 1:
if (newState < 1) {
if (this.mDestroyed) {
if (f.getAnimatingAway() != null) {
View v = f.getAnimatingAway();
f.setAnimatingAway((View)null);
v.clearAnimation();
} else if (f.getAnimator() != null) {
Animator animator = f.getAnimator();
f.setAnimator((Animator)null);
animator.cancel();
}
}
if (f.getAnimatingAway() == null && f.getAnimator() == null) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom CREATED: " + f);
}
if (!f.mRetaining) {
// 执行framgnet的onDestroy周期方法
f.performDestroy();
this.dispatchOnFragmentDestroyed(f, false);
} else {
f.mState = 0;
}
// 执行framgnet的onDetach周期方法
f.performDetach();
this.dispatchOnFragmentDetached(f, false);
if (!keepActive) {
if (!f.mRetaining) {
this.makeInactive(f);
} else {
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
}
}
} else {
f.setStateAfterAnimating(newState);
newState = 1;
}
}
}
}
if (f.mState != newState) {
Log.w("FragmentManager", "moveToState: Fragment state for " + f + " not updated inline; " + "expected state " + newState + " found " + f.mState);
f.mState = newState;
}
}
复制代码
继续从FragmentManagerImpl类的moveFragmentToExpectedState(f)方法中提及,该方法中又会继续调用moveToState方法,这个方法和上面的moveToState方法不一样,这俩方法是同名不一样参的方法,该方法中会根据fragment的mState自身的状态值和newState传过来的状态值进行比较来区分:当前fragment是走建立阶段的周期方法仍是销毁阶段的周期方法,进一步再经过fragment的mState判断到底要走哪一个fragment的周期方法,具体标注可看代码注释哦。
Fragment的7种状态(mState):
static final int INVALID_STATE = -1; // 做为null值的非法状态
static final int INITIALIZING = 0; // 没有被create
static final int CREATED = 1; // 已经create
static final int ACTIVITY_CREATED = 2; // Activity已经完成了create
static final int STOPPED = 3; // 彻底建立,还没start
static final int STARTED = 4; // 已经create和start,尚未resume
static final int RESUMED = 5; // 已经完成create,start和resume
咱们最后说一下回退栈(FragmentManagerImpl的成员mBackStack),其实咱们在cooimt操做时咱们就已经设置了“回退栈”内的元素。从新看一下该部分代码:
// FragmentManagerImpl类:
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (FragmentManagerImpl.DEBUG) {
Log.v("FragmentManager", "Run: " + this);
}
records.add(this);
isRecordPop.add(false);
if (this.mAddToBackStack) {
this.mManager.addBackStackState(this);
}
return true;
}
void addBackStackState(BackStackRecord state) {
if (this.mBackStack == null) {
this.mBackStack = new ArrayList();
}
this.mBackStack.add(state);
}
复制代码
咱们回顾一下上面的逻辑,在执行BackStackRecord类(实现了OpGenerator接口)的方法generateOps时,就已经将当前的BackStackRecord入栈啦。而BackStackRecord出栈主要是调用以下几个方法:
PopBackStackState类 实现了 OpGenerator 接口,具体实现以下:
若咱们本身主动调用popBackStack两个方法之一,实际上就是调用了enqueueAction方法,并传入PopBackStackState类的新建立实例,而此时isRecordPop集合里存的值就是true。在上面部分分析中也说明了isRecordPop集合中存的元素对代码逻辑的影响。最后会致使界面显示的是上一个fragment视图。
若是 回退栈 mBackStack 为空就终止出栈操做并返回 false,当name == null && id < 0 && (flags & POP_BACK_STACK_INCLUSIVE) == 0 (调用的是popBackStack()方法)时,把返回栈最后一个 BackStackRecord出栈。当 name 或者 id 被指定的时候,倒序遍历 mBackStack ,若是遇到 name 或者 id 相符就退出循环,此时 index 为第一次匹配到的下标,若是flags==POP_BACK_STACK_INCLUSIVE 继续遍历返回栈,直至栈底或者遇到不匹配的跳出循环。最后出栈全部 BackStackRecord。