Android之Fragment源码级彻底解析上
来源:互联网 发布:大数据时代 四大挑战 编辑:程序博客网 时间:2024/06/08 10:00
1 举栗子
下面的例子我使用了2个Fragment作为Activity的布局
ContentFragment的布局
ContentFragment#fragment_content<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#00cccc" android:id="@+id/content" android:layout_height="match_parent"><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="40sp" android:textColor="#FFFFFF" android:text="CONTENT"/></RelativeLayout>ContentFragment.java
public class ContentFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root=inflater.inflate(R.layout.fragment_content,container,false); return root; }}
MenuFragment的布局
MenuFragment#fragment_menu<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#cccc00" android:id="@+id/menu" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="40sp" android:textColor="#FFFFFF" android:text="MENU"/></RelativeLayout>MenuFragment.java
public class MenuFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root=inflater.inflate(R.layout.fragment_menu,container,false); return root; }}
然后是ManiActivity的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" android:orientation="vertical"> <FrameLayout android:id="@+id/fragment" android:layout_width="match_parent" android:layout_height="350dp"/> <Button android:id="@+id/bnt_content" android:text="SWITCH_CONTENT" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:background="#00cccc" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/bnt_menu" android:text="SWITCH_MENU" android:background="#cccc00" android:layout_width="match_parent" android:layout_height="wrap_content" /></LinearLayout>ManiActivity.java
public class MainActivity extends Activity implements View.OnClickListener { private Button jump; private FrameLayout frame; private ContentFragment mContentFragment; private Button mContent; private Button mMenu; private MenuFragment mMenuFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initView(); setDefaultFragment(); Log.e("activity", "____onCreate" + "___" + savedInstanceState+"_________Main"); } private void setDefaultFragment() { FragmentManager fm=getFragmentManager(); FragmentTransaction transaction=fm.beginTransaction(); mContentFragment=new ContentFragment(); transaction.replace(R.id.fragment,mContentFragment); transaction.commit(); } private void initView() { mContent = (Button) findViewById(R.id.bnt_content); mMenu = (Button) findViewById(R.id.bnt_menu); mContent.setOnClickListener(this); mMenu.setOnClickListener(this); } @Override public void onClick(View v) { FragmentManager fm=getFragmentManager(); FragmentTransaction transaction=fm.beginTransaction(); switch (v.getId()) { case R.id.bnt_content: if (mContentFragment!=null){ mContentFragment=new ContentFragment(); } transaction.replace(R.id.fragment,mContentFragment); break; case R.id.bnt_menu: if (mMenuFragment==null){ mMenuFragment=new MenuFragment(); } transaction.replace(R.id.fragment,mMenuFragment); break; } transaction.commit(); }}点击两个按钮可以切换相应的Fragment
2 Fragment家族常用API详解
Fragment常用的三个类:
android.app.Fragment 主要用于定义Fragment
android.app.FragmentManager 主要用于在Activity中操作Fragment
android.app.FragmentTransaction 保证一些列Fragment操作的原子性
(1)Fragment
Fragment是Android3.0引入的API,相比Activity更轻量级、更灵活
他有两种使用方式
(1.1)静态生成
静态写在xml中,和其他控件无差别
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:name="com.example.huyucheng.test.FirstFragment" android:layout_width="match_parent" android:layout_height="wrap_content"/> <fragment android:name="com.example.huyucheng.test.SecondFragment" android:layout_width="match_parent" android:layout_height="wrap_content"/></LinearLayout>(1.2)代码动态生成
FragmentManager fm=getFragmentManager(); FragmentTransaction transaction=fm.beginTransaction(); mFirstFragment=new FirstFragment(); transaction.add(R.id.fragment,mFirstFragment); transaction.addToBackStack(null); transaction.commit();
(2)FragmentManager
获取FragmentManager的方式:
getFragmentManager() // v4中,getSupportFragmentManager
fragmentManager并不是全局唯一的,而是每个activity都有一个自己的FragmentManager,内部有自己的状态mCurState,对应外部activity的生命周期状态。它提供和activity中fragment交互的API
(3)FragmentTransaction
主要的操作都是FragmentTransaction的方法,FragmentTransaction封装了一系列对fragment的操作,并一次性执行这些操作
FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务
transaction .commit();//提交一个事务
transaction.add() //往Activity中添加一个Fragment
transaction.remove() //从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。
transaction.addToBackStack(null);//回退栈
transaction.replace()//使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
transaction.hide()//隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
transaction.show()//显示之前隐藏的Fragment
detach()//会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
attach()//重建view视图,附加到UI上并显示。
上面涉及到Fragment回退栈,视图移除等概念,可能很多人不太理解,莫慌,等我慢慢分析
3 源码分析
我们就从这个最常见的用法开始分析
FragmentManager fm=getFragmentManager(); FragmentTransaction transaction=fm.beginTransaction(); mFirstFragment=new FirstFragment(); transaction.replace(R.id.fragment,mFirstFragment); transaction.commit();(1)Activity
先来看看getFragmentManager()能得到什么
public FragmentManager getFragmentManager() { return mFragments.getFragmentManager(); }
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());(2)FragmentController
public FragmentManager getFragmentManager() { return mHost.getFragmentManagerImpl(); }FragmentController 里面真正执行的是mHost(FragmentHostCallback),很明显,这是一个桥接模式
(3)FragmentHostCallback
FragmentManagerImpl getFragmentManagerImpl() { return mFragmentManager; }
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();从这里可以看出我们经常调用的getFragmentManager()方法获取的其实是FragmentManagerImpl ,所以重点在FragmentManagerImpl 中
(4)FragmentManagerImpl
再来看看FragmentTransaction transaction=fm.beginTransaction();
@Override public FragmentTransaction beginTransaction() { return new BackStackRecord(this); }所以这里我们常用的FragmentTransaction是BackStackRecord类型,重点在BackStackRecord里面
(5)BackStackRecord(实现了Runnble,replace、add、remove等操作都在run中进行)
再来分析 transaction.replace(R.id.fragment,mFirstFragment);
public FragmentTransaction replace(int containerViewId, Fragment fragment) { return replace(containerViewId, fragment, null); }
public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) { ...... doAddOp(containerViewId, fragment, tag, OP_REPLACE); return this; }replace中只有doAddOp方法,我们常说replace执行了remove和add,接下来我们就来看看doAddOp是不是真的执行了remove和add
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) { fragment.mFragmentManager = mManager;...... //下面的代码让fragment容器的id(mContainerId)和mFragmentId都指向framelayout布局id if (containerViewId != 0) { 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; }//Op是操作类,很显然,这里只是进行了简单的赋值操作 Op op = new Op(); op.cmd = opcmd; op.fragment = fragment; addOp(op); }
上面的containerViewId是我们例子中MainActivity存放fragment的framelayout布局id,mManager就是FragmentManagerImpl ,
很显然,doAddOp只是对Op操作类进行了赋值,并没有做其他操作,再来看看addOp
void addOp(Op op) { if (mHead == null) { mHead = mTail = op; } else { op.prev = mTail; mTail.next = op; mTail = op; } op.enterAnim = mEnterAnim; op.exitAnim = mExitAnim; op.popEnterAnim = mPopEnterAnim; op.popExitAnim = mPopExitAnim; mNumOp++; }
addOp简单的把当前赋值后的op增加到双链表的尾部,很显然,这里维护了一个双链表。
op.prev = mTail;和mTail.next = op;让op插入了双链表尾部,mTail = op;让mTail指针指向了当前的op(当前fragment),这里的链表使用的是尾插法,每个新插进来的fragment都位于尾部。
这里Op是BackStackRecord的内部类,是一个双链表数据结构
static final class Op { Op next; Op prev; int cmd; Fragment fragment; int enterAnim; int exitAnim; int popEnterAnim; int popExitAnim; ArrayList<Fragment> removed; }依然,这里也没有看到replace所谓的remove和add操作,我们的replace操作在哪里执行的呢?接下来只有 transaction.commit();了
public int commit() { return commitInternal(false); }
int commitInternal(boolean allowStateLoss) { ...... mManager.enqueueAction(this, allowStateLoss); return mIndex; }还是没干啥,看看mManager.enqueueAction
(5)FragmentManagerImpl
public void enqueueAction(Runnable action, boolean allowStateLoss) { ...... synchronized (this) { ...... if (mPendingActions == null) { mPendingActions = new ArrayList<Runnable>(); } mPendingActions.add(action); if (mPendingActions.size() == 1) { mHost.getHandler().removeCallbacks(mExecCommit); mHost.getHandler().post(mExecCommit); } } }mPendingActions是专门装载Runnable的集合,从名字就可以看出enqueueAction就是把Runnable (BackStackRecord)加入到了集合中,
然后执行了mExecCommit(Runnble)
Runnable mExecCommit = new Runnable() { @Override public void run() { execPendingActions(); } };再来看看execPendingActions
public boolean execPendingActions() {...... while (true) { int numActions; synchronized (this) { numActions = mPendingActions.size(); if (mTmpActions == null || mTmpActions.length < numActions) { mTmpActions = new Runnable[numActions]; } //mPendingActions中保存的Runnble转移到了Runnble数组mTmpActions中 mPendingActions.toArray(mTmpActions); mPendingActions.clear(); mHost.getHandler().removeCallbacks(mExecCommit); } //在这里执行了Op操作 for (int i=0; i<numActions; i++) { mTmpActions[i].run(); mTmpActions[i] = null; } ...... return didSomething; }
可以看到最终在execPendingActions中的mTmpActions[i].run()(即BackStackRecord.run())执行了transaction.replace操作,接下来是重中之重(6)BackStackRecord
public void run() { ...... Op op = mHead; while (op != null) { switch (op.cmd) { case OP_ADD: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } break; case OP_REPLACE: { //获取新fragment Fragment f = op.fragment; int containerId = f.mContainerId; //mManager.mAdded集合存放FragmentManagerImpl中的fragment if (mManager.mAdded != null) { for (int i = 0; i < mManager.mAdded.size(); i++) { //old是mAdded集合最前面的一个fragment Fragment old = mManager.mAdded.get(i); //frameLayout布局的id相同进进行操作 if (old.mContainerId == containerId) {//如果fragment已经存在 if (old == f) { op.fragment = f = null; } else { if (op.removed == null) { op.removed = new ArrayList<Fragment>(); } //把old fragment放入删除集合中 op.removed.add(old); old.mNextAnim = op.exitAnim; if (mAddToBackStack) { old.mBackStackNesting += 1; if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Bump nesting of " + old + " to " + old.mBackStackNesting); } } //删除old fragment mManager.removeFragment(old, mTransition, mTransitionStyle); } } } } if (f != null) { f.mNextAnim = op.enterAnim;//增加新fragment mManager.addFragment(f, false); } } break; case OP_REMOVE: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.removeFragment(f, mTransition, mTransitionStyle); } break; case OP_HIDE: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.hideFragment(f, mTransition, mTransitionStyle); } break; case OP_SHOW: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.showFragment(f, mTransition, mTransitionStyle); } break; case OP_DETACH: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.detachFragment(f, mTransition, mTransitionStyle); } break; case OP_ATTACH: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.attachFragment(f, mTransition, mTransitionStyle); } break; } op = op.next; } mManager.moveToState(mManager.mCurState, mTransition, mTransitionStyle, true); if (mAddToBackStack) { mManager.addBackStackState(this); } }trasaction.replace对应上面的OP_REPLACE,具体操作就是操作先删除全部的 fragment,然后增加新的fragment,mManager.removeFragment和mManager.addFragment都是对mAdded集合进行增删操作,
上面还可以看到
transaction.add()
transaction.remove()
transaction.addToBackStack(null);
transaction.replace()
transaction.hide()
transaction.show()
detach()
attach()
一系列方法的所有操作,到这里我们的整个fragment流程跑完了,接下来我们还会重点分析run方法里面的操作
上面的run方法在对这一系列Op处理完后,调用了下面的方法:
mManager.moveToState(mManager.mCurState, mTransition, mTransitionStyle, true);显然这个方法用于改变Fragment的状态,这个方法最终会将FragmentManager的状态赋值给fragment,另外这个方法会根据不同的state调用各种onAttach, Fragment.performXXX,进而调到用户自己override的fragment的各种生命周期方法,比如onCreate、onCreateView等等
流程:ActivityThread.performXXX执行Activity的生命周期,fragmentManager的dispatchXXX方法跟着也执行了,fragmentManager的dispatchXXX中的moveToState根据不同的state调用fragment的生命周期函数
上面的run方法最后还调用下面的方法
if (mAddToBackStack) { mManager.addBackStackState(this); }很显然就是判断fragment是否要加入回退栈,其中mAddToBackStack就是在我们熟悉的addToBackStack方法中置true的
public FragmentTransaction addToBackStack(String name) { if (!mAllowAddToBackStack) { throw new IllegalStateException( "This FragmentTransaction is not allowed to be added to the back stack."); } mAddToBackStack = true; mName = name; return this; }
Fragment的所有可能状态:
static final int INVALID_STATE = -1; // Invalid state used as a null value. static final int INITIALIZING = 0; // Not yet created. static final int CREATED = 1; // Created. static final int ACTIVITY_CREATED = 2; // The activity has finished its creation. static final int STOPPED = 3; // Fully created, not started. static final int STARTED = 4; // Created and started, not resumed. static final int RESUMED = 5; // Created started and resumed.FragmentManager中有一堆public void dispatchxxx这样的方法用于改变Fragment的生命周期状态
(7)FragmentManager
public void dispatchCreate() { mStateSaved = false; moveToState(Fragment.CREATED, false); } public void dispatchActivityCreated() { mStateSaved = false; moveToState(Fragment.ACTIVITY_CREATED, false); } public void dispatchStart() { mStateSaved = false; moveToState(Fragment.STARTED, false); } public void dispatchResume() { mStateSaved = false; moveToState(Fragment.RESUMED, false); } public void dispatchPause() { moveToState(Fragment.STARTED, false); } public void dispatchStop() { moveToState(Fragment.STOPPED, false); } public void dispatchDestroyView() { moveToState(Fragment.CREATED, false); } public void dispatchDestroy() { mDestroyed = true; execPendingActions(); moveToState(Fragment.INITIALIZING, false); mHost = null; mContainer = null; mParent = null; }这些方法正好是和activity的生命周期对应起来,也就是说这些方法是随着activity进入到不同的生命周期而被调用的,即mCurState的值是被这些方法触发设置的。比如activity进入到了Resume状态,那么FragmentManagerImpl.mCurState也就等于Fragment.RESUMED
4 Fragment操作专项解析
之前在网上看多很多人各种分析,但是很多是基于UI结果来分析操作方法的区别,总感觉分析的不够科学,下面是基于源码分析操作方法,一直深入到最底层
再来回顾下那些难以区分的方法
transaction.add() //往Activity中添加一个Fragment
transaction.remove() //从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。
transaction.addToBackStack(null);//回退栈
transaction.replace()//使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
transaction.hide()//隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
transaction.show()//显示之前隐藏的Fragment
transaction.detach//会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
transaction.attach()//重建view视图,附加到UI上并显示。
接下来结合BackStackRecord中run方法的源码来看
(1)transaction.add()
case OP_ADD: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } break;mManager.addFragment主要就是将fragment加入到了集合中,并改变fragment状态
public void addFragment(Fragment fragment, boolean moveToStateNow) { ...... mAdded.add(fragment); ...... if (moveToStateNow) { moveToState(fragment); } } }
(2)transaction.remove()
case OP_REMOVE: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.removeFragment(f, mTransition, mTransitionStyle); } break;
mManager.removeFragment主要就是将fragment从集合中删除,以及改变fragment的状态
public void removeFragment(Fragment fragment, int transition, int transitionStyle) { ...... if (mAdded != null) { mAdded.remove(fragment); } ...... moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, transition, transitionStyle, false); } }
(3)transaction.replace()
case OP_REPLACE: { Fragment f = op.fragment; int containerId = f.mContainerId; if (mManager.mAdded != null) { for (int i = 0; i < mManager.mAdded.size(); i++) { Fragment old = mManager.mAdded.get(i); ...... mManager.removeFragment(old, mTransition, mTransitionStyle); ...... } } if (f != null) { f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } } break;
这个上面已经分析了,移除所有老fragment,再把新的加进来
(4)transaction.hide()case OP_HIDE: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.hideFragment(f, mTransition, mTransitionStyle); }
public void hideFragment(Fragment fragment, int transition, int transitionStyle) { if (DEBUG) Log.v(TAG, "hide: " + fragment); if (!fragment.mHidden) { fragment.mHidden = true; if (fragment.mView != null) { Animator anim = loadAnimator(fragment, transition, false, transitionStyle); if (anim != null) { anim.setTarget(fragment.mView); final Fragment finalFragment = fragment; anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (finalFragment.mView != null) {//改变fragment根View的visibility属性为Gone finalFragment.mView.setVisibility(View.GONE); } } }); anim.start(); } else { fragment.mView.setVisibility(View.GONE); } } ...... fragment.onHiddenChanged(true); } }transaction.hide()只是改变fragment根View的visibility为gone
case OP_SHOW: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.showFragment(f, mTransition, mTransitionStyle); } break;
public void showFragment(Fragment fragment, int transition, int transitionStyle) { if (fragment.mHidden) { fragment.mHidden = false; if (fragment.mView != null) { Animator anim = loadAnimator(fragment, transition, true, transitionStyle); if (anim != null) { anim.setTarget(fragment.mView); setHWLayerAnimListenerIfAlpha(fragment.mView, anim); anim.start(); } fragment.mView.setVisibility(View.VISIBLE); } fragment.onHiddenChanged(false); } }transaction.show只是让fragment.hidden==true的fragment根View的visibility属性为VISIBLE
(6)transaction.attach()
case OP_ATTACH: { Fragment f = op.fragment; f.mNextAnim = op.enterAnim; mManager.attachFragment(f, mTransition, mTransitionStyle); } break;
public void attachFragment(Fragment fragment, int transition, int transitionStyle) { if (fragment.mDetached) { fragment.mDetached = false; if (!fragment.mAdded) { if (mAdded == null) { mAdded = new ArrayList<Fragment>(); } if (mAdded.contains(fragment)) { throw new IllegalStateException("Fragment already added: " + fragment); } mAdded.add(fragment); fragment.mAdded = true; moveToState(fragment, mCurState, transition, transitionStyle, false); } } }
(7)transaction.detach()
case OP_DETACH: { Fragment f = op.fragment; f.mNextAnim = op.exitAnim; mManager.detachFragment(f, mTransition, mTransitionStyle); } break;
public void detachFragment(Fragment fragment, int transition, int transitionStyle) { if (!fragment.mDetached) { fragment.mDetached = true; if (fragment.mAdded) { // We are not already in back stack, so need to remove the fragment. if (mAdded != null) { if (DEBUG) Log.v(TAG, "remove from detach: " + fragment); mAdded.remove(fragment); } if (fragment.mHasMenu && fragment.mMenuVisible) { mNeedMenuInvalidate = true; } fragment.mAdded = false; moveToState(fragment, Fragment.CREATED, transition, transitionStyle, false); } } }detach的时候onPause、onStop、onDestroyView会被调用,onDestroy、onDetach不会被调用
(8)transaction.addToBackStack(null)
我们调用transaction.addToBackStack后实际让mAddToBackStack = true;然后run方法里面再执行 mManager.addBackStackState(this);
public FragmentTransaction addToBackStack(String name) { if (!mAllowAddToBackStack) { throw new IllegalStateException( "This FragmentTransaction is not allowed to be added to the back stack."); } mAddToBackStack = true; mName = name; return this; }
if (mAddToBackStack) { mManager.addBackStackState(this); }
void addBackStackState(BackStackRecord state) { if (mBackStack == null) { mBackStack = new ArrayList<BackStackRecord>(); } mBackStack.add(state); reportBackStackChanged(); }
5 总结
(1)在上面的过程中我们跑通了fragment常用API的整个流程
FragmentManager fm=getFragmentManager(); FragmentTransaction transaction=fm.beginTransaction(); mFirstFragment=new FirstFragment(); transaction.add(R.id.fragment,mFirstFragment); transaction.addToBackStack(null); transaction.commit();其中FragmentManager 的实现类FragmentManagerImpl
FragmentTransaction 的实现类BackStackRecord,BackStackRecord的run方法包含了对fragment的所有操作
整个生命周期流程:ActivityThread.performXXX执行Activity的生命周期,fragmentManager的dispatchXXX方法跟着也执行了,fragmentManager的dispatchXXX中的moveToState根据不同的state调用fragment的生命周期函数
(2)show/hideFragment只是改变fragment根View的visibility,最多带上个动画效果,另外只有本身是hidden的fragment,调用show才起作用,否则没用的,fragment.onHiddenChanged会被触发;其次不会有生命周期callback触发,当然了这些操作的前提是已经被add了的fragment;
(3)addFragment的时候,不管加不加入回退栈都一样,经历的生命周期如下:onAttach、onCreate、onCreateView、onActivityCreate、onStart、onResume;
(4)removeFragment的时候,经历的生命周期如下:onPause、onStop、onDestroyView,如果不加回退栈还会继续走onDestroy、onDetach;remove的时候不仅从mAdded中移除fragment,也从mActive中移除了;
(5)attach/detachFragment的前提都是已经add了的fragment,其生命周期回调不受回退栈影响。attach的时候onCreateView、onActivityCreate、onStart、onResume会被调用;detach的时候onPause、onStop、onDestroyView会被调用,onDestroy、onDetach不会被调用;对应的fragment只是从mAdded中移除了
(6)remove、detachFragment的时候,当FragmentManagerImpl.makeInactive()被调用的话,fragment就变成了一个空壳,里面绝大部分字段都会被置空,注意只是系统内部自己管理的字段,假如你在自己的fragment子类中引入了新的字段,当你重用这些类的对象时要自己处理这种情况(即系统不会reset你自己造的字段)
void makeInactive(Fragment f) { ...... f.initState(); } void initState() { mIndex = -1; mWho = null; mAdded = false; mRemoving = false; mResumed = false; mFromLayout = false; mInLayout = false; mRestored = false; mBackStackNesting = 0; mFragmentManager = null; mChildFragmentManager = null; mHost = null; mFragmentId = 0; mContainerId = 0; mTag = null; mHidden = false; mDetached = false; mRetaining = false; mLoaderManager = null; mLoadersStarted = false; mCheckedForLoaderManager = false; }
这一篇章多次涉及到fragment的生命周期,下一篇篇章将对fragment的生命周期进行详解
- Android之Fragment源码级彻底解析上
- Android Fragment 源码解析
- Android-Fragment源码解析
- Android Fragment 从源码的角度去解析(上)
- Android Fragment 从源码的角度去解析(上)
- Android fragment源码全解析
- Android之Fragment 真正的完全解析(上)
- Android Fragment 解析(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- shell中>/dev/null 2>&1是什么鬼?
- keil分散加载文件sct写法
- c#获取软件在注册表中的安装信息
- Activity3---不经意的死掉onSaveInstanceState
- TABLE CONTROL使用方法(待整理)
- Android之Fragment源码级彻底解析上
- Apache2.2.22开启PathInfo模式的支持
- Dos之IF命令
- 简单服务器的问题避免
- 关系数据库的优化方法论基本是一致的
- 龟兔赛跑
- Dos之Call命令
- sql server中cast函数
- ABAP的PAI和PBO中的字段传递顺序