聊聊Fragment

355 阅读3分钟

前言

随着谷歌那边Jetpack单activity应用的流行,fragment以后用的概率会越来越高,对fragment有个完整的认识愈发重要。在我的个人印象中,对fragment的认识也是有点模糊,趁着周末有时间,直接瞅了瞅相关源码,顺手也记录一下。

整体介绍

Fragment如果看过相关源码的话可以简单的认为:Fragment就是一个具有生命周期的View.一个FragmentTransaction的完成就意味了一个ContainerView中移除添加view或者设置f.mView Visiblity的动作。当然口说无凭,我们直接fucking the source code.

源码流程介绍

我们先上一段比较简单常见的代码段:

    supportFragmentManager.beginTransaction()
           .replace(R.id.container, Fragment())
           .commit();

beginTransaction()返回了一个FragmentTransaction的子类对象BackStackRecord:

    //FragmentManagerImpl.java
    
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

紧接着我们看replace方法

    //FragmentTransaction.java
    //保存所有的options(操作)
    ArrayList<Op> mOps = new ArrayList<>();
    
    @NonNull
    public FragmentTransaction replace(@IdRes int containerViewId, @NonNull Fragment fragment,
            @Nullable String tag)  {
        if (containerViewId == 0) {
            throw new IllegalArgumentException("Must use non-zero containerViewId");
        }
        //添加一个Op 其opcmd 的类型为OP_REPLACE 后面会根据OP_REPLACE来做对应的操作
        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
        return this;
    }

    public void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
        
        ...

        //设置fragment的tag
        fragment.mTag = tag;
        
        ...
        
        //设置fragment的mContainerId
        fragment.mContainerId = fragment.mFragmentId = containerViewId;
    
        //将新的Op对象放到list中
        addOp(new Op(opcmd, fragment));
    }
    
    void addOp(Op op) {
        mOps.add(op);
        ...
    }

看完上面两个方法介绍,感觉前两个方法没做啥东西。。实际上replace方法只是为commit方法准备一些操作数据,commit才是真正的执行,commit方法执行流程比较复杂,我们忽略中间方法,简要描述一下执行流程:通过调用commit()方法,然后中间通过handler post了一个runnable,这个runnable里面的方法具体就是处理了Op对象Fragment,层层调用最终调到了moveToState方法中:

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                     boolean keepActive) {
     if (f.mState <= newState) {
          switch (f.mState) {
                ...
                case Fragment.INITIALIZING:
                ...
                // fall through 注意源码这一块并没有break 会继续往下执行
                case Fragment.CREATED:
                ...
                // fall through
                case Fragment.ACTIVITY_CREATED:
                ...
                case Fragment.STARTED:
     }
}

看moveToState 里面的switch分支,我们可以知道这个应该和fragment的生命周期有关系,并且有点核心哦。那么接下来我们介绍其中两个case中的源码:

 //FragmentManagerImpl.java
 
 case Fragment.INITIALIZING:

    // 源码日志:执行完这个case 我就要到fragment的created状态了
    if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
    ...
   //通知监听fragment生命周期的listener我即将要attach了
    dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
    //执行fragment的preformAttach方法,并回调了fragment的attach方法
    f.performAttach();
    //通知监听fragment生命周期的listener我已经attached了
    dispatchOnFragmentAttached(f, mHost.getContext(), false);

    //r如果fragment还没创建 则performCreate 和attach类似
    if (!f.mIsCreated) {
        dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
        //回调fragment的onCreate生命周期
        f.performCreate(f.mSavedFragmentState);
        dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
    } else {
        f.restoreChildFragmentState(f.mSavedFragmentState);
        f.mState = Fragment.CREATED;
    }
    // fall through

然后我们挑其中fragment.preformCreate()源码瞅瞅:

//fragment.java
 void performCreate(Bundle savedInstanceState) {
        ...
        //state状态更改为created
        mState = CREATED;
        mCalled = false;
        ...
        //回调onCreate方法
        onCreate(savedInstanceState);
        //isCreated为true
        mIsCreated = true;
         //通知lifeCycle onCreateEvent
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }

具体上面代码就不总结了,注释还是比较清晰的。接下来我们看看另外一个case的源码:

 case Fragment.CREATED:
    ...
    if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
    if (!f.mFromLayout) {
        ViewGroup container = null;
        if (f.mContainerId != 0) {
            //找到view 具体实现在activity中 就是一个findViewById
            container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
        }
        //给mContainer赋值
        f.mContainer = container;
        //回调onCreateView
        f.performCreateView(f.performGetLayoutInflater(
                f.mSavedFragmentState), container, f.mSavedFragmentState);
        if (f.mView != null) {
            f.mInnerView = f.mView;
            f.mView.setSaveFromParentEnabled(false);
            if (container != null) {
                //将我们重写的onCreateView返回的值 添加到container中
                container.addView(f.mView);
            }
           
            //回调onViewCreated
            f.onViewCreated(f.mView, f.mSavedFragmentState);
           ...
        }
    }
    
    //回调onActivityCreated
    f.performActivityCreated(f.mSavedFragmentState);
    dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
    ...

    // fall through

终于我们在这个case里看到了我们熟悉的view 和我们经常重写的onCreateView 和onViewCreated。。。 太难了。。。 到这基本上fragment算是和container绑定起来了。后续的比如onStart onResume等生命周期基本类似 大家自己挖掘一下就好了。。。