基于 support-fragment-26.0.0-alpha1
Fragment 的創(chuàng)建
Fragment 的使用離不開 FragmentActivity 卢肃,或者說 Fragment 必須依附于 FragmentActivity。
Fragment 可以在直接在 FragmentActivity 創(chuàng)建的時(shí)候垢夹,聲明在 xml 文件之中。也可以在 Activity 創(chuàng)建以后墓塌,動(dòng)態(tài)的創(chuàng)建桩皿。
-
方式一
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:id="@+id/test_frament" class="xxx.xxx.xxx.xxFragment" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
-
方式二
getSupportFragmentManager().beginTransaction().replace(R.id.fragment, new xxFragment()).commit();
這里有個(gè)問題?
Fragment 本身不是一個(gè) View 的子類衡楞。
在方式二中我們知道我們 new 了一個(gè) Fragment 交給 FragmentTransaction
那么!方式一是如何創(chuàng)建 Fragment的 敦姻?
在前面閱讀LayoutInflater 源碼 我們可以得知瘾境,xml 里面聲明的 View 都是通過 LayoutInflater 創(chuàng)建。那么 FragmentActivity 如何通過 xml 創(chuàng)建 Fragment 呢?
FragmentActivity 從 xml 創(chuàng)建 Fragment
先看下 FragmentActivity 的繼承關(guān)系
onCreateView 方法創(chuàng)建 Fragment
在 BaseFragmentActivityApi14 中發(fā)現(xiàn)以下代碼
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
final View v = dispatchFragmentsOnCreateView(parent, name, context, attrs);
if (v == null) {
return super.onCreateView(parent, name, context, attrs);
}
return v;
}
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
final View v = dispatchFragmentsOnCreateView(null, name, context, attrs);
if (v == null) {
return super.onCreateView(name, context, attrs);
}
return v;
}
abstract View dispatchFragmentsOnCreateView(View parent, String name,
Context context, AttributeSet attrs);
這里看到 BaseFragmentActivityApi14 繼承了 onCreateView 方法,并且聲明了一個(gè) dispatchFragmentsOnCreateView 方法暖呕。
FragmentActivity 實(shí)現(xiàn)了 dispatchFragmentsOnCreateView
@Override
final View dispatchFragmentsOnCreateView(View parent, String name, Context context,
AttributeSet attrs) {
return mFragments.onCreateView(parent, name, context, attrs);
}
最終 FragmentManager 中找到了 onCreateView 負(fù)責(zé)創(chuàng)建 Fragment
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!"fragment".equals(name)) {
return null;
}
……
if (fragment == null) {
fragment = mContainer.instantiate(context, fname, null);
……
addFragment(fragment, true);
……
}……
return fragment.mView;
}
FragmentContainer 中 instantiate 方法
public Fragment instantiate(Context context, String className, Bundle arguments) {
return Fragment.instantiate(context, className, arguments);
}
然后又回到了 Fragment 中
public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) {
try {
Class<?> clazz = sClassMap.get(fname);
……
Fragment f = (Fragment)clazz.newInstance();
……
return f;
} ……
}
可以看出,最終還是用了反射創(chuàng)建了 Fragment兑凿。 并且返回 fragment.mView 給 onCreateView
誰(shuí)調(diào)用 onCreateView ?
先看一段 LayoutInflater 中 createViewFromTag() 方法
try {
View view;
if (mFactory2 != null) {
view = mFactory2.onCreateView(parent, name, context, attrs);
} else if (mFactory != null) {
view = mFactory.onCreateView(name, context, attrs);
} else {
view = null;
}
if (view == null && mPrivateFactory != null) {
view = mPrivateFactory.onCreateView(parent, name, context, attrs);
}
if (view == null) {
final Object lastContext = mConstructorArgs[0];
mConstructorArgs[0] = context;
try {
if (-1 == name.indexOf('.')) {
view = onCreateView(parent, name, attrs);
} else {
view = createView(name, null, attrs);
}
} finally {
mConstructorArgs[0] = lastContext;
}
}
return view;
在 LayoutInflater 源碼 我們講到 mFactory2茵瘾、mFactory礼华、mPrivateFactory 全部為 null ,其實(shí)并不嚴(yán)謹(jǐn)拗秘。因?yàn)?Activity 也是一個(gè) Factory2 的實(shí)現(xiàn)圣絮。
在 Activity 的 attach() 方法調(diào)用了
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window) {
……
mWindow.getLayoutInflater().setPrivateFactory(this);
……
}
而 BaseFragmentActivityApi14 又一次重載了 Activity 實(shí)現(xiàn)的 Factory2. onCreateView 。并攔截 <fragment> 標(biāo)簽交給 FragmentActivity 的 dispatchFragmentsOnCreateView() 方法雕旨。
總結(jié)一個(gè)簡(jiǎn)單的 UML 圖
Fragment 執(zhí)行生命周期
跟隨 FragmentActivity 生命周期
在 FragmentActivity 的 onCreate() 中
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
……
mFragments.dispatchCreate();
}
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
public void dispatchCreate() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.CREATED, false);
mExecutingActions = false;
}
其中 moveToState(Fragment.CREATED, false) 會(huì)執(zhí)行 Fragment 的 onCreate() 方法扮匠。
然后在 onStart() 方法中調(diào)用 mFragments.dispatchStart() ,執(zhí)行 Fragment 的 onStart()方法 凡涩。
然后在 onResume() 是會(huì)調(diào)用 mHandler.sendEmptyMessage(MSG_RESUME_PENDING)
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REALLY_STOPPED:
if (mStopped) {
doReallyStop(false);
}
break;
case MSG_RESUME_PENDING:
onResumeFragments();
mFragments.execPendingActions();
break;
default:
super.handleMessage(msg);
}
}
};
接著會(huì)執(zhí)行 onResumeFragments() -> mFragments.dispatchResume() , 執(zhí)行 Fragment 的 onResume() 方法棒搜。
以此類推 Fragment 的生命周期跟隨 FragmentActivity 的生命周期依次執(zhí)行。
在 FragmentActivity 中動(dòng)態(tài)添加 Fragment
在 FragmentActivity 中動(dòng)態(tài)添加 Fragment 需要獲得一個(gè) FragmentTransaction
然后通過 FragmentTransaction.replace(R.id.fragment, new xxFragment()) 或者 FragmentTransaction.add(R.id.fragment, new xxFragment()) 添加一個(gè)創(chuàng)建的 Fragment 到 FragmentActivity(其實(shí)是 FragmentManager)
最后通過 FragmentTransaction.commit() 顯示 Fragment活箕。
獲得 FragmentTransaction
獲得 FragmentTransaction 首先獲得 FragmentManager 力麸。
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
mFragments 是一個(gè) FragmentController
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
FragmentController 的所有方法,都是包裹這 HostCallbacks() 來實(shí)現(xiàn)的。HostCallbacks 是 FragmentHostCallback 的子類
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
其中 mHost 就是 HostCallbacks 的實(shí)例末盔。HostCallbacks 繼承 FragmentHostCallback
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManager;
}
在 FragmentHostCallback 中有成員變量
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
所以 FragmentTransaction 由 FragmentManagerImpl 創(chuàng)建。FragmentManagerImpl 又是 FragmentManager 的實(shí)例座慰。
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
所以最終我們獲得的 FragmentTransaction 是一個(gè) BackStackRecord 實(shí)例陨舱。
獲得 FragmentTransaction 的 add() 、replace()
這兩個(gè)方法都在 BackStackRecord 中 版仔,有很多 add()游盲、replace() 方法,這里貼兩個(gè)重要的
@Override
public FragmentTransaction add(int containerViewId, Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
@Override
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;
}
可以看出無論 add()蛮粮、replace() 最終都調(diào)用 doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) 方法益缎,只是 opcmd 值不同。
最終會(huì)添加一個(gè) Op 對(duì)象
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
……
addOp(new Op(opcmd, fragment));
}
void addOp(Op op) {
mOps.add(op);
op.enterAnim = mEnterAnim;
op.exitAnim = mExitAnim;
op.popEnterAnim = mPopEnterAnim;
op.popExitAnim = mPopExitAnim;
}
獲得 FragmentTransaction 的 commit()
commit() 同樣在 BackStackRecord 中實(shí)現(xiàn)然想。
@Override
public int commit() {
return commitInternal(false);
}
然后執(zhí)行
int commitInternal(boolean allowStateLoss) {
……
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
mIndex 是 BackStackRecord 在 FragmentManager 中保存的一個(gè) ArrayList 的位置莺奔。
然后執(zhí)行
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
……
scheduleCommit();
}
}
接著執(zhí)行
private void scheduleCommit() {
synchronized (this) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
mExecCommit 是一個(gè) Runnable
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
然后就快到關(guān)鍵方法
public boolean execPendingActions() {
ensureExecReady(true);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
doPendingDeferredStart();
return didSomething;
}
接著執(zhí)行
private void optimizeAndExecuteOps(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop) {
……
int startIndex = 0;
for (int recordNum = 0; recordNum < numRecords; recordNum++) {
……
executeOpsTogether(records, isRecordPop, recordNum, optimizeEnd);
……
}
}
……
}
然后到了 executeOpsTogether
private void executeOpsTogether(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
……
if (!allowOptimization) {
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
false);
}
executeOps(records, isRecordPop, startIndex, endIndex);
……
}
其中 FragmentTransition.startTransitions 最終會(huì)執(zhí)行 addToFirstInLastOut
然后執(zhí)行 manager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
在 moveToState 中,會(huì)執(zhí)行 Fragment 的 onAttach() 方法
其中的 executeOps(records, isRecordPop, startIndex, endIndex) 之中執(zhí)行 void executeOps()
mManager.moveToState(mManager.mCurState, true);
因?yàn)榇藭r(shí) Activity 已經(jīng)是 Resume 狀態(tài)变泄,所以 mManager.mCurState == RESUMED
然后 mManager.moveToState 會(huì)一次執(zhí)行
Fragment.performCreateView()
Fragment.performActivityCreated()
Fragment.performStart()
Fragment.performResume()
通過上面可以發(fā)現(xiàn) void moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive) 是最關(guān)鍵的方法令哟。Fragment 的各個(gè)狀態(tài)都是通過這個(gè)方法進(jìn)行切換的。
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
……
if (f.mState <= newState) { // Fragment 從后臺(tái)到顯示
……
switch (f.mState) {
case Fragment.INITIALIZING:
if (newState > Fragment.INITIALIZING) {
……
f.onAttach(mHost.getContext());
……
}
case Fragment.CREATED:
……
if (newState > Fragment.CREATED) {
……
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
……
}
f.performActivityCreated(f.mSavedFragmentState);
……
}
case Fragment.ACTIVITY_CREATED:
if (newState > Fragment.ACTIVITY_CREATED) {
f.mState = Fragment.STOPPED;
}
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.performStart();
dispatchOnFragmentStarted(f, false);
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.performResume();
dispatchOnFragmentResumed(f, false);
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) {// Fragment 從顯示到后臺(tái)
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
f.performPause();
dispatchOnFragmentPaused(f, false);
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
f.performStop();
dispatchOnFragmentStopped(f, false);
}
case Fragment.STOPPED:
if (newState < Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
f.performReallyStop();
}
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
……
f.performDestroyView();
dispatchOnFragmentViewDestroyed(f, false);
……
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
……
}
}
}
……
}