原来一直只是使用Fragment,除了对一些常用API很熟悉外,对Fragment的内部原理还是不清楚,索性花了几天的时间,去阅读了Fragment相关的源码,从整体上对Fragment的框架有了一定深度的认识。当然,Fragment相关的类很多,Fragment内部的成员也很多,我目前还无法弄清楚Fragment的每一个细节,但整体上的正确认识有助于我们对细节的把握,也能对问题的查找、定位以及解决起到指导作用。这篇文章我准备先从Fragment被添加到Activity中的过程入手,观察一些相关的类和调用流程,然后针对一些具体的问题,在源码中找到解释做出总结。
FragmentActivity、HostCallbacks和FragmentController
从我们平常使用的动态添加Fragment说起,看一下其中是哪些类在起作用。
MyFragment f = new MyFragment();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content, f)
.commit();
其中getSupportFragmentManager()方法返回了一个FragmentManager对象。
先来看看mFragments这个成员,它是一个FragmentController对象。创建的时候还传入了一个继承FragmentHostCallback类的HostCallbacks对象。
//FragmentActivity.java
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
先来看下这个HostCallbacks对象,初始化的时候传入了调用FragmentController.createController(new HostCallbacks())的FragmentActivity的实例的引用。
//HostCallbacks.java
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
构造器中只调用了父类的构造器,继续看HostCallbacks的父类FragmentHostCallback。构造器利用传进来的FragmentActivity的引用,为自己的成员变量赋值,可以看到,这个类的实例不仅持有了Activity的引用,还持有它的context,handler等。重点关注下mFragmentManager这个成员,它在HostCallbacks初始化的时候也初始化,是一个 FragmentManagerImpl对象。
//FragmentHostCallback.java
FragmentHostCallback(FragmentActivity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
}
FragmentHostCallback(Activity activity, Context context, Handler handler,
int windowAnimations) {
mActivity = activity;
mContext = context;
mHandler = handler;
mWindowAnimations = windowAnimations;
}
private final Activity mActivity;
final Context mContext;
private final Handler mHandler;
final int mWindowAnimations;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
/** The loader managers for individual fragments [i.e. Fragment#getLoaderManager()] */
private SimpleArrayMap<String, LoaderManager> mAllLoaderManagers;
/** Whether or not fragment loaders should retain their state */
private boolean mRetainLoaders;
/** The loader manger for the fragment host [i.e. Activity#getLoaderManager()] */
private LoaderManagerImpl mLoaderManager;