Activity 中使用 Fragment,一般为了兼容3.0以下低版本,会继承 FragmentActivity,然后在layout布局中添加,或者在代码中动态添加
onCreate():
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(id, fragment);
transaction.commit();
我们看一下,getSupportFragmentManager() 对应的是
FragmentActivity:
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
HostCallbacks 是 FragmentActivity 中的内部类,继承了 FragmentHostCallback<FragmentActivity> ;我们看看 FragmentController 中代码
private final FragmentHostCallback<?> mHost;
public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback<?> callbacks) {
mHost = callbacks;
}
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
这里 FragmentHostCallback<?> 泛型中的类型是 FragmentActivity,上面有提到 HostCallbacks 继承了 FragmentHostCallback<FragmentActivity>;因此
mFragments.getSupportFragmentManager() 调用的是 FragmentController 中的 getSupportFragmentManager() 方法,即 mHost.getFragmentManagerImpl(),我们看看
HostCallbacks 的代码,它里面没这个方法,去它的父类 FragmentHostCallback 中找
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManager;
}
我们看看 FragmentManagerImpl 是什么,它继承了 FragmentManager ,实现了接口 LayoutInflaterFactory,看名字也知道是一个具体逻辑管理的实现类,好家伙,仅仅一行代码,就嵌套了这么多层。
我们看第二行代码,FragmentTransaction transaction = fm.beginTransaction(); 开启一个事物,此时对应的是 FragmentManagerImpl 中的方法
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
这个事物管理器,就是 BackStackRecord,下一步, transaction.replace(id, fragment); 对应的则是
public FragmentTransaction replace(int containerViewId, Fragment fragment) {
return replace(containerViewId, fragment, null);
}
public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
if (containerViewId == 0) {
throw new IllegalArgumentException("Must use non-zero containerViewId");
}
doAddOp(containerViewId, fragment, tag, OP_REPLACE);
return this;
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
fragment.mFragmentManager = mManager;
if (tag != null) {
fragment.mTag = tag;
}
if (containerViewId != 0) {
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
Op op = new Op();
op.cmd = opcmd;
op.fragment = fragment;
addOp(op);
}
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++;
}
创建了 Op op = new Op(); 对象,把当前fragment和 static final int OP_REPLACE = 2; 放置进去, Op 是一个数据结构容器,通过 addOp(op) 方法,可以看出,它是一个双链表,从前往后排。
最后看看 transaction.commit(); 提交事物,我们看看它的逻辑
final FragmentManagerImpl mManager;
public int commit() {
return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
我们看看 FragmentManagerImpl 中的代码 enqueueAction 方法
public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<Runnable>();
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
public boolean execPendingActions() {
boolean didSomething = false;
while (true) {
int numActions;
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
break;
}
numActions = mPendingActions.size();
if (mTmpActions == null || mTmpActions.length < numActions) {
mTmpActions = new Runnable[numActions];
}
mPendingActions.toArray(mTmpActions);
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
mExecutingActions = true;
for (int i=0; i<numActions; i++) {
mTmpActions[i].run();
mTmpActions[i] = null;
}
mExecutingActions = false;
didSomething = true;
}
if (mHavePendingDeferredStart) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null && f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
if (!loadersRunning) {
mHavePendingDeferredStart = false;
startPendingDeferredFragments();
}
}
return didSomething;
}
最终在主线程中执行 execPendingActions(); 方法,我们继续往里面看,enqueueAction() 方法中把 runnable 加入了mPendingActions集合中,execPendingActions() 中把它转换到mTmpActions 数组中,下面有个for循环方法,mTmpActions[i].run(); 这里执行了 runnable 的run() 方法,这个runnable是什么呢? enqueueAction(this, allowStateLoss)方法中把BackStackRecord 添加了进去,BackStackRecord 实现了 Runnable 接口,那么我们看看 run() 方法中的代码
public void run() {
...
Op op = mHead;
while (op != null) {
int enterAnim = state != null ? 0 : op.enterAnim;
int exitAnim = state != null ? 0 : op.exitAnim;
switch (op.cmd) {
case OP_ADD: {
Fragment f = op.fragment;
f.mNextAnim = enterAnim;
mManager.addFragment(f, false);
} break;
case OP_REPLACE: {
Fragment f = op.fragment;
...
if (f != null) {
f.mNextAnim = enterAnim;
mManager.addFragment(f, false);
}
} break;
case OP_REMOVE: {
Fragment f = op.fragment;
f.mNextAnim = exitAnim;
mManager.removeFragment(f, transition, transitionStyle);
} break;
...
}
op = op.next;
}
mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
}
这里是简化版的,会执行到 switch中的 case OP_REPLACE 方法中,先把添加到Activity中的Fragment给清除掉,然后调用 mManager.addFragment(f, false); 方法,这个方法中有集合维护添加到activity中的fragment,最后看 moveToState() 方法,这个是重点
void moveToState(int newState, int transit, int transitStyle, boolean always) {
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No host");
}
if (!always && mCurState == newState) {
return;
}
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
moveToState(f, newState, transit, transitStyle, false);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
if (!loadersRunning) {
startPendingDeferredFragments();
}
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
}
这个方法中会更新 mCurState 值,先记住这一点。由于 addFragment() 时已经把fragment添加到 mActive 集合中,此时会执行moveToState(f, newState, transit, transitStyle,false) 方法,注意注意注意,真正的重点
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
...
if (f.mState < newState) {
...
switch (f.mState) {
case Fragment.INITIALIZING:
...
f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
f.mCalled = false;
f.onAttach(mHost.getContext());
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
mHost.onAttachFragment(f);
}
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
f.mRetaining = false;
if (f.mFromLayout) {
...
}
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
}
f.mContainer = container;
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
if (container != null) {
Animation anim = loadAnimation(f, transit, true,
transitionStyle);
if (anim != null) {
setHWLayerAnimListenerIfAlpha(f.mView, anim);
f.mView.startAnimation(anim);
}
container.addView(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.performStart();
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.performResume();
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
f.performPause();
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
f.performStop();
}
...
}
}
...
}
这里面是简化的代码, 注意看 if (f.mState < newState) {} 中的代码,此时会执行这里面的逻辑,我们发现switch中没有break,也就是说如果条件允许,会从上往下执行。
可能有人会问,为什么会是 f.mState < newState,从刚才添加的逻辑看到现在,似乎这两个值都是默认值,即0,怎么会一个小于另外一个呢?这是因为一开始我们直接分析Fragment的添加流程了,没有分析FragmentActivity中的 onCreate() 方法,我们看一下 onCreate 中有一行代码先执行,mFragments.dispatchCreate();
FragmentController 中
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
FragmentManagerImpl 中
public void dispatchCreate() {
mStateSaved = false;
moveToState(Fragment.CREATED, false);
}
void moveToState(int newState, boolean always) {
moveToState(newState, 0, 0, always);
}
void moveToState(int newState, int transit, int transitStyle, boolean always) {
...
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
moveToState(f, newState, transit, transitStyle, false);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
if (!loadersRunning) {
startPendingDeferredFragments();
}
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
}
最后这个方法上面出现过,我们发现,把 Fragment.CREATED 这个值传了进来,即 mCurState = Fragment.CREATED; 由于此时 mActive 为null,所以代码到此就停了,这里的一个重要操作就是给 mCurState 赋值了,我们看看 Fragment 中的几个常量值,
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.
此时我们在看上面的方法,if (f.mState < newState) 这个判断中,newsState 是从 mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);传进来的,指的是 mManager.mCurState ,即 CREATED ,值为1,而 Fragment 中的 mState 此时为默认值,是0,所以执行到这个 if(f.mState < newState) 中了。switch 中走到 case Fragment.INITIALIZING 中, f.mHost = mHost; f.onAttach(mHost.getContext()); 所以我们会在 Fragment 的 onAttach() 方法中获取 Activity,也可以通过 getActivity() 来获取,我们看一下
final public FragmentActivity getActivity() {
return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}
由于 f.mHost = mHost ,所以这里的 mHost 就是 FragmetnActivity 中的 HostCallbacks,它的基类里有该方法
Activity getActivity() {
return mActivity;
}
这里的 mActivity 就是通过构造方法传进去的,就是 FragmentActivity 本身。所以这两种方法都可以获取到 Fragment 所在的 Activity。
继续往下看, f.performCreate(f.mSavedFragmentState); 这里调用的是 Fragment 中的方法,一开始时 f.mSavedFragmentState 为null,我们看看该方法
void performCreate(Bundle savedInstanceState) {
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
}
mState = CREATED;
mCalled = false;
onCreate(savedInstanceState);
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onCreate()");
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(
FragmentActivity.FRAGMENTS_TAG);
if (p != null) {
if (mChildFragmentManager == null) {
instantiateChildFragmentManager();
}
mChildFragmentManager.restoreAllState(p, null);
mChildFragmentManager.dispatchCreate();
}
}
}
这里面重点看两行代码, mState = CREATED; onCreate(savedInstanceState); 这两行代码 mState = CREATED,是把 Fragment 中的 mState 的值,有0变为了1,onCreate() 方法是我们回调时使用,用来填充代码,写自己的逻辑。 if (f.mFromLayout) 这里走不到, f.mFromLayout 意思是在布局layout中静态填充的写法,咱们这里是通过代码动态生成的,所以
跳过去。 由于这里的switch语句没有使用break,并且上面的Fragment中 mState = CREATED, mState的值变了, 所以到了下一个 case Fragment.CREATED 满足条件,我们看一下,if (newState > Fragment.CREATED) 这个判断中, newState 目前是 CREATED,所以不会执行if的语句,这个case里面也没有break,所以继续找下一个case,但接下来的都不满足条件了。
我们在 Activity 中的 onCreate() 中执行本文开头的添加 Fragment 的方法, commit() 的分析暂时结束,可能有人就有疑惑了,Fragment怎么只有 onCreate() 的生命周期回调,怎么没其他的?它是怎么生成布局的?不用急,接下来继续分析。我们知道 Activity 生命周期,onCreate() 执行后会执行 onStart() ,我们看看 FragmentActivity 中的方法
protected void onStart() {
super.onStart();
mStopped = false;
mReallyStopped = false;
mHandler.removeMessages(MSG_REALLY_STOPPED);
if (!mCreated) {
mCreated = true;
mFragments.dispatchActivityCreated();
}
mFragments.noteStateNotSaved();
mFragments.execPendingActions();
mFragments.doLoaderStart();
// NOTE: HC onStart goes here.
mFragments.dispatchStart();
mFragments.reportLoaderStart();
}
其他的可以不看,重点看 mFragments.dispatchActivityCreated() 和 mFragments.dispatchStart(); 这两行代码, 上面的加了mCreated 标识判断,说明该调用只会执行一次,我们看看对应的方法
public void dispatchActivityCreated() {
mHost.mFragmentManager.dispatchActivityCreated();
}
public void dispatchActivityCreated() {
mStateSaved = false;
moveToState(Fragment.ACTIVITY_CREATED, false);
}
void moveToState(int newState, boolean always) {
moveToState(newState, 0, 0, always);
}
void moveToState(int newState, int transit, int transitStyle, boolean always) {
...
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
moveToState(f, newState, transit, transitStyle, false);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
...
}
}
我们发现,最终还是调用了 moveToState() 方法,并且 mCurState 的值为 ACTIVITY_CREATED,传入到 moveToState() 方法中的 newState 值也为 ACTIVITY_CREATED,我们看看 if(f.mState < newState) 中,这时候 f.mState 的值为 CREATED, 而 newState 的值为 ACTIVITY_CREATED,所以适配到了 case Fragment.CREATED,此时就满足了if (newState >
Fragment.CREATED) 的判断,我们看看代码, 由于fragmetn是动态添加的,所以会走到 if (!f.mFromLayout) 里面,这里的 f.mContainerId ,是在 transaction.replace(id,fragment) 时 doAddOp()方法中赋值,也就是我们设置的layout中的容器的id; container = (ViewGroup)mContainer.onFindViewById(f.mContainerId); 这里的 mContainer 是通过attachController() 方法赋值的,它对应的是 FragmentActivity 中的 HostCallbacks ,mContainer.onFindViewById() 对应的是 HostCallbacks 中的 onFindViewById() 方法
public View onFindViewById(int id) {
return FragmentActivity.this.findViewById(id);
}
我们看到这就明白了了,原来最终还是通过activity的 findViewById 方法来找到layout中的 ViewGroup,下一步就是调用了 Fragment 的 performCreateView() 方法,同时接收生成的view,
View performCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
}
return onCreateView(inflater, container, savedInstanceState);
}
@Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return null;
}
我们重写的就是 onCreateView() 方法,继续往下看,如果生成的 f.mView 和 container 都不为 null,会执行container.addView(f.mView); 看到这明白了,原来就是用ViewGroup 来添加 view;接着是 f.onViewCreated(f.mView, f.mSavedFragmentState); f.performActivityCreated(f.mSavedFragmentState); 生命周期回调,注意
void performActivityCreated(Bundle savedInstanceState) {
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
}
mState = ACTIVITY_CREATED;
mCalled = false;
onActivityCreated(savedInstanceState);
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onActivityCreated()");
}
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchActivityCreated();
}
}
重点关注两行代码, mState = ACTIVITY_CREATED; onActivityCreated(savedInstanceState); 老规矩, Fragment 的mState值在这里再次改变了,我们看看下一个case,发现if (newState > Fragment.STOPPED) 不满足条件,其他case也不满足,就此停止。
我们再看看 mFragments.dispatchStart(); 它对应的逻辑一样,
public void dispatchStart() {
mStateSaved = false;
moveToState(Fragment.STARTED, false);
}
最终把 moveToState() 中 newState 的值修改为 STARTED,此时switch中会执行到 case Fragment.ACTIVITY_CREATED 中,if (newState > Fragment.STOPPED) 满足条件,执行f.performStart(); 方法,
void performStart() {
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
mChildFragmentManager.execPendingActions();
}
mState = STARTED;
mCalled = false;
onStart();
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onStart()");
}
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchStart();
}
if (mLoaderManager != null) {
mLoaderManager.doReportStart();
}
}
重点关注 mState = STARTED; onStart(); 这两行代码, Fragment 中的 mState 值再再次改变。 switch 中 继续往下执行,case Fragment.STARTED 中if语句不满足条件,不会执行。
FragmentActivity 中 onStart() 中分析完毕,下面看看 onResume() 中的代码
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_RESUME_PENDING:
onResumeFragments();
mFragments.execPendingActions();
break;
}
}
};
protected void onResume() {
super.onResume();
mHandler.sendEmptyMessage(MSG_RESUME_PENDING);
mResumed = true;
mFragments.execPendingActions();
}
protected void onResumeFragments() {
mFragments.dispatchResume();
}
老套路,这一次会调用 moveToState(Fragment.RESUMED, false); 这次把方法中 newState 值修改为 RESUMED,switch中 case Fragment.STARTED 满足条件,if语句也满足,
执行 f.performResume() 方法,
void performResume() {
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
mChildFragmentManager.execPendingActions();
}
mState = RESUMED;
mCalled = false;
onResume();
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onResume()");
}
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchResume();
mChildFragmentManager.execPendingActions();
}
}
还是重点两行代码,mState = RESUMED; onResume(); Fragment 中 mState 值赋值为 RESUMED,同时执行 onResume() 生命周期回调。
Fragment 的创建流程就是这样,如果我们是在view的onClick点击事件中执行了本文开头的代码,此时FragmentActivity已经执行完 onResume() 方法了,那么 FragmentManagerState中的 mCurState 值已经是 RESUMED,这时候通过事务管理器执行 commit() 方法后,switch 语句会 if (f.mState < newState) 中,依次执行 case Fragment.INITIALIZING 、 case Fragment.CREATED 、case Fragment.ACTIVITY_CREATED 、case Fragment.STARTED, 一次性执行到底。 这个是创建过程,那么销毁过程能,同理,也是根据 FragmentActivity 的生命周期控制的,和前面的套路一样,根据 onPause()、 onStop()、 onDestroy() 来调用 Fragment 的方法。Activity 的 onPause() 中会调用 moveToState(Fragment.STARTED,false); 此时传进去的 newState 为 STARTED, 此时 if (f.mState < newState) 就不满足条件了,所以执行 else 操作,此时执行 case Fragment.RESUMED 里操作,if判断满足条件,执行 f.performPause(); 其他的地方同理。这里说一下 case Fragment.ACTIVITY_CREATED,这里面会执行 f.performDestroyView(); f.mContainer.removeView(f.mView); 在这里
ViewGroup 移除了里面的 view。 而 Fragment.CREATED 中,f.onDetach() 之后会执行 makeInactive(f) 方法,它里面有一行代码 f.initState(); Fragment 中好些成员变量在此被置空,感兴趣的可以看一下, getActivity() 拿到的 activity 为null的原因就清楚了。
Fragment 一定要保持一个无参构造方法,Android Studio 创建Fragment时会有默认的创建方法,大家可以试试,为什么要这样呢,有什么好处?比如创建 BlankFragment ,
public class BlankFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
public BlankFragment() {
// Required empty public constructor
}
public static BlankFragment newInstance(String param1, String param2) {
BlankFragment fragment = new BlankFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
}
我们知道,Activity 在内存吃紧时会造成内存回收,然后会在 onCreate()中通过 bundle 来恢复数据,同样调用牵涉到了 Fragment,
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
public void restoreAllState(Parcelable state, List<Fragment> nonConfigList) {
mHost.mFragmentManager.restoreAllState(state, nonConfigList);
}
void restoreAllState(Parcelable state, List<Fragment> nonConfig){}
void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
...
FragmentManagerState fms = (FragmentManagerState)state;
if (fms.mActive == null) return;
...
mActive = new ArrayList<Fragment>(fms.mActive.length);
if (mAvailIndices != null) {
mAvailIndices.clear();
}
for (int i=0; i<fms.mActive.length; i++) {
FragmentState fs = fms.mActive[i];
if (fs != null) {
// 关注点
Fragment f = fs.instantiate(mHost, mParent);
mActive.add(f);
fs.mInstance = null;
} else {
mActive.add(null);
if (mAvailIndices == null) {
mAvailIndices = new ArrayList<Integer>();
}
if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i);
mAvailIndices.add(i);
}
}
...
}
关注点 的地方,Fragment f = fs.instantiate(mHost, mParent); 调用的是 FragmentState 中
FragmentState:
public Fragment instantiate(FragmentHostCallback host, Fragment parent) {
...
mInstance = Fragment.instantiate(context, mClassName, mArguments);
...
return mInstance;
}
Fragment:
public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) {
try {
Class<?> clazz = sClassMap.get(fname);
if (clazz == null) {
clazz = context.getClassLoader().loadClass(fname);
sClassMap.put(fname, clazz);
}
Fragment f = (Fragment)clazz.newInstance();
if (args != null) {
args.setClassLoader(f.getClass().getClassLoader());
f.mArguments = args;
}
return f;
} catch (ClassNotFoundException e) {
...
}
}
Fragment f = (Fragment)clazz.newInstance(); 这一行说明了重点,是通过反射调用无参构造创建了Fragment对象,然后通过 f.mArguments = args; 来赋值,所以 AS 推荐的写法是这样。