Fragment例項化,Fragment生命週期原始碼分析
Fragment的例項化,Fragment的生命週期
- android.support.v4.app.FragmentActivity#onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
mFragments.attachActivity(this, mContainer, null);
// Old versions of the platform didn't do this!
if (getLayoutInflater().getFactory() == null ) {
getLayoutInflater().setFactory(this);
}
super.onCreate(savedInstanceState);
// ....
}
這裡主要是對LayoutInflater設定了Factory(注意:在同一個Activity中使用getBaseContext和使用Activity.this通過LayoutInflater.from獲得的LayoutInflater是同一個,但是不同的Activity獲得的不是同一個),這個Factory的作用主要是用來作為hook,便於FragmentActivity通過“fragment”Tag來建立Fragment例項。
然後設定android.app.Activity#setContentView(int) 會觸發android.view.LayoutInflater#inflate(int, android.view.ViewGroup)->android.view.LayoutInflater#createViewFromTag。
2. android.view.LayoutInflater#createViewFromTag
View view;
if (mFactory2 != null) {
view = mFactory2.onCreateView(parent, name, viewContext, attrs);
} else if (mFactory != null) {
view = mFactory.onCreateView(name, viewContext, attrs);
} else {
view = null;
}
這裡會呼叫mFactory的onCreateView方法,這裡的mFactory也就是FragmentActivity。
3. android.support.v4.app.FragmentActivity#onCreateView
@Override
public View onCreateView(String name, @NonNull Context context, @NonNull AttributeSet attrs) {
if (!"fragment".equals(name)) {
return super.onCreateView(name, context, attrs);
}
final View v = mFragments.onCreateView(name, context, attrs);
if (v == null) {
return super.onCreateView(name, context, attrs);
}
return v;
}
先判斷是否是“fragment”Tag,如果不是,返回super.onCreateView,父類是直接返回null,這樣會丟給LayoutInflater中自己處理。如果是“fragment”Tag,那麼會呼叫FragmentManagerImpl的onCreateView去處理。
4. android.support.v4.app.FragmentManagerImpl#onCreateView
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
/// ...
if (fragment == null) {
fragment = Fragment.instantiate(context, fname);
fragment.mFromLayout = true;
fragment.mFragmentId = id != 0 ? id : containerId;
fragment.mContainerId = containerId;
fragment.mTag = tag;
fragment.mInLayout = true;
fragment.mFragmentManager = this;
fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
addFragment(fragment, true);
}
// ...
return fragment.mView;
}
這裡會直接呼叫Fragment.instantiate方法去構造Fragment例項。
5. android.support.v4.app.Fragment#instantiate(android.content.Context, java.lang.String, android.os.Bundle)
public static Fragment instantiate(Context context, String fname, Bundle args) {
Class<?> clazz = sClassMap.get(fname);
if (clazz == null) {
// Class not found in the cache, see if it's real, and try to add it
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;
}
直接通過class.newInstance反射呼叫了Fragment的無參構造來獲得新的Fragment例項。同時在第4步最後會呼叫addFragment來把新的Fragment新增到FragmentManagerImpl中。
6. android.support.v4.app.FragmentManagerImpl#addFragment
if (moveToStateNow) {
moveToState(fragment);
}
這個方法核心點會去進行Fragment的狀態變換。
7. android.support.v4.app.FragmentManagerImpl#moveToState(android.support.v4.app.Fragment, int, int, int, boolean)
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
if (f.mSavedFragmentState != null) {
f.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mTarget = getFragment(f.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG);
if (f.mTarget != null) {
f.mTargetRequestCode = f.mSavedFragmentState.getInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
}
f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
if (!f.mUserVisibleHint) {
f.mDeferStart = true;
if (newState > Fragment.STOPPED) {
newState = Fragment.STOPPED;
}
}
}
f.mActivity = mActivity;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mActivity.mFragments;
f.mCalled = false;
f.onAttach(mActivity);
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
mActivity.onAttachFragment(f);
}
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
f.mRetaining = false;
if (f.mFromLayout) {
// For fragments that are part of the content view
// layout, we need to instantiate the view immediately
// and the inflater will take care of adding it.
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
if (Build.VERSION.SDK_INT >= 11) {
ViewCompat.setSaveFromParentEnabled(f.mView, false);
} else {
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
}
這個方法依次呼叫了onAttach,onCreate,onCreateView,onViewCreated方法,這也就是Fragment的生命週期中比較重要的幾個方法,同時,因為這些方法都是在Activity.onCreate中進行的,所以這些方法都會在onActivityCreated之前呼叫。
8. android.support.v4.app.FragmentActivity#onStart
@Override
protected void onStart() {
super.onStart();
mStopped = false;
mReallyStopped = false;
mHandler.removeMessages(MSG_REALLY_STOPPED);
if (!mCreated) {
mCreated = true;
mFragments.dispatchActivityCreated();
}
// ...
mFragments.dispatchStart();
// ...
}
這裡會呼叫onActivityCreated和onStart方法。
以上就是Fragment建立的過程和一些生命週期的方法的呼叫順序。
結論:
1. Fragment必須有無參構造,否則無法被例項化。
2. Fragment生命週期:Activity.onCreate->Fragment.onAttach->Fragment.onCreate->Fragment.onCreateView->Fragment.onViewCreated->Activity.onStart->Fragment.onActivityCreated->Fragment.onStart