基于 support-fragment-26.0.0-alpha1
Fragment 的創建
Fragment 的使用離不開 FragmentActivity ,或者說 Fragment 必須依附于 FragmentActivity。
Fragment 可以在直接在 FragmentActivity 創建的時候,聲明在 xml 文件之中。也可以在 Activity 創建以后,動態的創建。
-
方式一
<?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();
這里有個問題?
Fragment 本身不是一個 View 的子類。
在方式二中我們知道我們 new 了一個 Fragment 交給 FragmentTransaction
那么!方式一是如何創建 Fragment的 ?
在前面閱讀LayoutInflater 源碼 我們可以得知,xml 里面聲明的 View 都是通過 LayoutInflater 創建。那么 FragmentActivity 如何通過 xml 創建 Fragment 呢?
FragmentActivity 從 xml 創建 Fragment
先看下 FragmentActivity 的繼承關系
onCreateView 方法創建 Fragment
在 BaseFragmentActivityApi14 中發現以下代碼
@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 方法,并且聲明了一個 dispatchFragmentsOnCreateView 方法。
FragmentActivity 實現了 dispatchFragmentsOnCreateView
@Override
final View dispatchFragmentsOnCreateView(View parent, String name, Context context,
AttributeSet attrs) {
return mFragments.onCreateView(parent, name, context, attrs);
}
最終 FragmentManager 中找到了 onCreateView 負責創建 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;
} ……
}
可以看出,最終還是用了反射創建了 Fragment。 并且返回 fragment.mView 給 onCreateView
誰調用 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 ,其實并不嚴謹。因為 Activity 也是一個 Factory2 的實現。
在 Activity 的 attach() 方法調用了
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 實現的 Factory2. onCreateView 。并攔截 <fragment> 標簽交給 FragmentActivity 的 dispatchFragmentsOnCreateView() 方法。
總結一個簡單的 UML 圖
Fragment 執行生命周期
跟隨 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) 會執行 Fragment 的 onCreate() 方法。
然后在 onStart() 方法中調用 mFragments.dispatchStart() ,執行 Fragment 的 onStart()方法 。
然后在 onResume() 是會調用 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);
}
}
};
接著會執行 onResumeFragments() -> mFragments.dispatchResume() , 執行 Fragment 的 onResume() 方法。
以此類推 Fragment 的生命周期跟隨 FragmentActivity 的生命周期依次執行。
在 FragmentActivity 中動態添加 Fragment
在 FragmentActivity 中動態添加 Fragment 需要獲得一個 FragmentTransaction
然后通過 FragmentTransaction.replace(R.id.fragment, new xxFragment()) 或者 FragmentTransaction.add(R.id.fragment, new xxFragment()) 添加一個創建的 Fragment 到 FragmentActivity(其實是 FragmentManager)
最后通過 FragmentTransaction.commit() 顯示 Fragment。
獲得 FragmentTransaction
獲得 FragmentTransaction 首先獲得 FragmentManager 。
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
mFragments 是一個 FragmentController
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
FragmentController 的所有方法,都是包裹這 HostCallbacks() 來實現的。HostCallbacks 是 FragmentHostCallback 的子類
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
其中 mHost 就是 HostCallbacks 的實例。HostCallbacks 繼承 FragmentHostCallback
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManager;
}
在 FragmentHostCallback 中有成員變量
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
所以 FragmentTransaction 由 FragmentManagerImpl 創建。FragmentManagerImpl 又是 FragmentManager 的實例。
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
所以最終我們獲得的 FragmentTransaction 是一個 BackStackRecord 實例。
獲得 FragmentTransaction 的 add() 、replace()
這兩個方法都在 BackStackRecord 中 ,有很多 add()、replace() 方法,這里貼兩個重要的
@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() 最終都調用 doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) 方法,只是 opcmd 值不同。
最終會添加一個 Op 對象
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 中實現。
@Override
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;
}
mIndex 是 BackStackRecord 在 FragmentManager 中保存的一個 ArrayList 的位置。
然后執行
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
……
scheduleCommit();
}
}
接著執行
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 是一個 Runnable
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
然后就快到關鍵方法
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;
}
接著執行
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 最終會執行 addToFirstInLastOut
然后執行 manager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
在 moveToState 中,會執行 Fragment 的 onAttach() 方法
其中的 executeOps(records, isRecordPop, startIndex, endIndex) 之中執行 void executeOps()
mManager.moveToState(mManager.mCurState, true);
因為此時 Activity 已經是 Resume 狀態,所以 mManager.mCurState == RESUMED
然后 mManager.moveToState 會一次執行
Fragment.performCreateView()
Fragment.performActivityCreated()
Fragment.performStart()
Fragment.performResume()
通過上面可以發現 void moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive) 是最關鍵的方法。Fragment 的各個狀態都是通過這個方法進行切換的。
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
……
if (f.mState <= newState) { // Fragment 從后臺到顯示
……
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 從顯示到后臺
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) {
……
}
}
}
……
}