引言
通常我们在Activity的onCreate生命周期中导入如下代码:
FragmentTransaction ft = getFragmentManager().beginTransaction();//1
ft.add(R.id.fragment_area, fragment, "fragment");//2
ft.commit();
注解1:
getFragmentManager()获取的是FragmentManagerImpl 对象。final class FragmentManagerImpl extends FragmentManager。
而FragmentManager是一个抽象类。abstract class FragmentManager
getFragmentManager().beginTransaction()获取的是BackStackRecord对象
注解2:
R.id.fragment_area是setContentView的layout对应的id,一定是ViewGroup对象(后面会有说明),例如LinearLayout、FrameLayout等
fragment是Fragment的对象
关键类
frameworks/base/core/java/android/app
FragmentManager.java(FragmentManagerImpl)
BackStackRecord
Fragment
关键分析
注:8.1系统代码为例
BackStackRecord.java
ft.add(R.id.fragment_area, fragment, "fragment");
public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
doAddOp(containerViewId, fragment, tag, OP_ADD);
return this;
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
······
fragment.mFragmentManager = mManager;
if (tag != null) {
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
throw new IllegalStateException("Can't change tag of fragment "
+ fragment + ": was " + fragment.mTag
+ " now " + tag);
}
fragment.mTag = tag;
}
if (containerViewId != 0) {
······
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
addOp(new Op(opcmd, fragment));
}
从这里可以看到,我们初始化了fragment的很多变量,特别是
fragment.mContainerId = fragment.mFragmentId = containerViewId;
FragmentManager.java
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
······
switch (f.mState) {
······
case Fragment.CREATED:
// This is outside the if statement below on purpose; we want this to run
// even if we do a moveToState from CREATED => *, CREATED => CREATED, and
// * => CREATED as part of the case fallthrough above.
ensureInflatedFragmentView(f);
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;//1
if (f.mContainerId != 0) {
if (f.mContainerId == View.NO_ID) {
throwException(new IllegalArgumentException(
"Cannot create fragment "
+ f
+ " for a container view with no id"));
}
container = mContainer.onFindViewById(f.mContainerId);//2
if (container == null && !f.mRestored) {
String resName;
try {
resName = f.getResources().getResourceName(f.mContainerId);
} catch (NotFoundException e) {
resName = "unknown";
}
throwException(new IllegalArgumentException(
"No view found for id 0x"
+ Integer.toHexString(f.mContainerId) + " ("
+ resName
+ ") for fragment " + f));
}
}
f.mContainer = container;
f.mView = f.performCreateView(f.performGetLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);//3
if (f.mView != null) {
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
container.addView(f.mView);//4
}
if (f.mHidden) {
f.mView.setVisibility(View.GONE);
}
f.onViewCreated(f.mView, f.mSavedFragmentState);
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
false);
// Only animate the view if it is visible. This is done after
// dispatchOnFragmentViewCreated in case visibility is changed
f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
&& f.mContainer != null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
······
}
注解1,我们可以看到有一个ViewGroup,而ViewGroup怎么来的呢?
注解2说明了来处,跟踪代码你会知道:
container对象是Activity的内部类HostCallbacks
mContainer.onFindViewById(f.mContainerId);其实就是Activity.this.findViewById(f.mContainerId),而这个就是我们特别熟悉的方法
f.mContainerId在上面的时候已经分析了,是Activity的R.id.fragment_area
注解3,表明f.mView是怎么来的?跟踪代码你会发现就是通过Fragment.onCreateView产生
注解4,就是将f.mView放到ViewGroup中,这里就是把Activity的View和Fragment的View关联起来
总结
Activity传入给Fragment的是父类,Fragment是将自己的子类全部加载到Activity的父类中
网友评论