Fragment之添加显示流程源码分析

==本文所引用的代码均为support-v4-23.0.1包中的源码,使用‘…’表示省略部分代码。==

当在Activity的onCreate方法中通过一下方式添加Fragment,运行程序,便可以修饰在屏幕上。

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();
    transaction.add(resId, fragmentA);
    transaction.commit();

这几行代码让Fragment经历了怎样的一番旅途,最终被关联到宿主Activity并显示。我准备扒一扒support-v4-23.0.0的源码,探索这一段神奇的旅途。

请尊重博主劳动成果,转载请标明原文链接。

一 相关的类

与此相关的类主要有10个,分别为:

FragmentManger为抽象类,定义对Fragment的操作行为,子类为FragmentMangerImplFragmentMangerImpl又实现了LayoutInflaterFactory接口,是真正对Fragment执行初始化,显示和移除等等操作的类。

FragmentTransaction为抽象类,定义对Fragment操作事务行为,子类为BackStackRecordBackStackRecord又实现了Runnable和FragmentManger.BackStackEntry接口,是执行Fragment添加,显示,隐藏和移除等等事务的类。OpBackStackRecord的静态内部类,当使用FragmentTransaction添加,替换,隐藏,移除等等操作便会在BackStackRecord对象中生成一个记录操作行为和Fragment的Op对象,该对象以链表的方式存储在BackStackRecord中。

FragmentHostCallback为抽象类,又继承了FragmentContainer,子类为FragmentActivity的内部类HostCallback

FragmentController封装对FragmentMangerImplHostCallback获取和操作的方法。

FragmentActivity用作Fragment的容器。

类图(Fragment的全家福):
这里写图片描述

流程分析

一,获取FragmentManager

在我们自定义的Activity中经常使用使用getSupportFragmentManager方法获取当前的FragmentManager(即FragmentMagagerImpl对象),那就先看看FragmentActivity类中的代码:

public FragmentManager getSupportFragmentManager() {
    return mFragments.getSupportFragmentManager();

}

mFragments是什么类型,何时初始化与赋值?接着往FragmentActivity中查看:

//在对象创建是便已赋值
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

创建HostCallbacks对象,那就看看它的构造方法代码:

public HostCallbacks() {
            //调用父类FragmentHostCallback的构造方法进行初始化
            super(FragmentActivity.this /*fragmentActivity*/);

}

接着继续看FragmentHostCallback代码:

public abstract class FragmentHostCallback<E> extends FragmentContainer {
   
    //当前关联的FragmentActivity对象
    private final Activity mActivity;
    //当前关联的Context对象,其实就是FragmentActivity对象
    final Context mContext;
    //当前FragmentActivity的mHandler属性
    private final Handler mHandler;
    final int mWindowAnimations;
    //FragmentActivity获取的FragmentManager就是这个属性
    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
    //当前key为who,value为加载器LoaderManagerImpl
    private SimpleArrayMap<String, LoaderManager> mAllLoaderManagers;
    //
    private LoaderManagerImpl mLoaderManager;
  private boolean mCheckedForLoaderManager;
  private boolean mLoadersStarted;

  public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
        this(null /*activity*/, context, handler, windowAnimations);
    }

    //FragmentActivity的内部类HostCallbacks调用赋值的构造方法
    FragmentHostCallback(FragmentActivity activity) {
        //使用activity给mContext赋值,activity.mHandler给mHandler赋值
        this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
    }

    //执行赋值
    FragmentHostCallback(Activity activity, Context context, Handler handler, int windowAnimations) {
        Activity = activity;
        mContext = context;
        mHandler = handler;
        mWindowAnimations = windowAnimations;
    }
    ...
}

再往回看看FragmentActivity的onCreate方法:

protected void onCreate(@Nullable Bundle savedInstanceState) {
    //**这一步很重要**
    //将FragmentController的mHost赋值给HostCallBack的mFragmentManager,便完成了当前Activity与FramgmentManger关联。
    mFragments.attachHost(null /*parent*/);
    super.onCreate(savedInstanceState);

    NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();
    if (nc != null) {
        mFragments.restoreLoaderNonConfig(nc.loaders);
    }
    if (savedInstanceState != null) {
        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
    }
    //通知mFragmentManager当前Activity执行了onCreate
    mFragments.dispatchCreate();
}

FragmentController中attachHost和dispatchCreate方法代码:

public void attachHost(Fragment parent) {
    mHost.mFragmentManager.attachController(mHost, mHost /*container*/, parent);
}

public void dispatchCreate() {

    mHost.mFragmentManager.dispatchCreate();

}

调用FragmentManagerImpl相关方法和属性的代码:

public void attachController(FragmentHostCallback host, FragmentContainer container, Fragment parent) {
    if (mHost != null) throw new IllegalStateException("Already attached");
    //将FragmentController中的mHost赋值给FragmentManagerImpl的mHost,自此便完成当前Activity与FramgmentManger关联
    mHost = host;
    mContainer = container;
    mParent = parent;
}

//FragmentManagerImpl当前状态值,默认为初始化
int mCurState = Fragment.INITIALIZING;

public void dispatchCreate() {
    mStateSaved = false;
    //更新当前状态mCurState为Fragment.CREATED
    moveToState(Fragment.CREATED, false);
}

void moveToState(int newState, boolean always) {
    moveToState(newState, 0, 0, always);
}

void moveToState(int newState, int transit, int transitStyle, boolean always) {
    if (mHost == null && newState != Fragment.INITIALIZING) {
        throw new IllegalStateException("No host");
    }
    if (!always && mCurState == newState) {
        return;
    }
    //更新当前状态mCurState为Fragment.CREATED
    mCurState = newState;
    //当从FragmentActivity的onCreate执行到此时,由于还未有添加Fragment,则mActive为null,便返回。
    //执行完这些代码后,FragmentManagerImpl的mCurState为Fragment.CREATED
    if (mActive != null) {
        boolean loadersRunning = false;
        for (int i=0; i<mActive.size(); i++) {
            Fragment f = mActive.get(i);
            if (f != null) {
                moveToState(f, newState, transit, transitStyle, false);
                ...
            }
        }
        ...
    }
}

当Activity的onCreate方法执行完super.onCreate(),我们便能够通过getSupportFragmentManager方法获取到一个可以正常使用的FragmentManagerImpl对象。

二,获取FragmentTransaction

调用FragmentManager的beginTransaction()方法获取FragmentTransaction。看看代码,究竟执行了哪些操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值