Android进阶旅程

Fragment 源码学习,从源码理解 Fragment 生命周

2017-09-25  本文已影响399人  看我眼前007
基于 support-fragment-26.0.0-alpha1

Fragment 的创建

Fragment 的使用离不开 FragmentActivity ,或者说 Fragment 必须依附于 FragmentActivity。

Fragment 可以在直接在 FragmentActivity 创建的时候,声明在 xml 文件之中。也可以在 Activity 创建以后,动态的创建。

  1. 方式一

     <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
     
         <fragment
            android:id="@+id/test_frament"
            class="xxx.xxx.xxx.xxFragment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
     </LinearLayout>
    
  2. 方式二

     getSupportFragmentManager().beginTransaction().replace(R.id.fragment, new xxFragment()).commit();
    

这里有个问题?

Fragment 本身不是一个 View 的子类。
在方式二中我们知道我们 new 了一个 Fragment 交给 FragmentTransaction
那么!方式一是如何创建 Fragment的 ?

在前面阅读LayoutInflater 源码 我们可以得知,xml 里面声明的 View 都是通过 LayoutInflater 创建。那么 FragmentActivity 如何通过 xml 创建 Fragment 呢?

FragmentActivity 从 xml 创建 Fragment

先看下 FragmentActivity 的继承关系

fragment_01.png
onCreateView 方法创建 Fragment

在 BaseFragmentActivityApi14 中发现以下代码

@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
    final View v = dispatchFragmentsOnCreateView(parent, name, context, attrs);
    if (v == null) {
        return super.onCreateView(parent, name, context, attrs);
    }
    return v;
}

@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    final View v = dispatchFragmentsOnCreateView(null, name, context, attrs);
    if (v == null) {
        return super.onCreateView(name, context, attrs);
    }
    return v;
}

abstract View dispatchFragmentsOnCreateView(View parent, String name,
        Context context, AttributeSet attrs);

这里看到 BaseFragmentActivityApi14 继承了 onCreateView 方法,并且声明了一个 dispatchFragmentsOnCreateView 方法。

FragmentActivity 实现了 dispatchFragmentsOnCreateView

@Override
final View dispatchFragmentsOnCreateView(View parent, String name, Context context,
        AttributeSet attrs) {
    return mFragments.onCreateView(parent, name, context, attrs);
}

最终 FragmentManager 中找到了 onCreateView 负责创建 Fragment

@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
    if (!"fragment".equals(name)) {
        return null;
    }

    ……
    if (fragment == null) {
        fragment = mContainer.instantiate(context, fname, null);
        ……
        addFragment(fragment, true);
        ……
    }……
    return fragment.mView;
}

FragmentContainer 中 instantiate 方法

public Fragment instantiate(Context context, String className, Bundle arguments) {
    return Fragment.instantiate(context, className, arguments);
}

然后又回到了 Fragment 中

public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) {
    try {
        Class<?> clazz = sClassMap.get(fname);
        ……
        Fragment f = (Fragment)clazz.newInstance();
        ……
        return f;
    } ……
}    

可以看出,最终还是用了反射创建了 Fragment。 并且返回 fragment.mView 给 onCreateView

谁调用 onCreateView ?

先看一段 LayoutInflater 中 createViewFromTag() 方法

try {
    View view;
    if (mFactory2 != null) {
        view = mFactory2.onCreateView(parent, name, context, attrs);
    } else if (mFactory != null) {
        view = mFactory.onCreateView(name, context, attrs);
    } else {
        view = null;
    }
    if (view == null && mPrivateFactory != null) {
        view = mPrivateFactory.onCreateView(parent, name, context, attrs);
    }
    if (view == null) {
        final Object lastContext = mConstructorArgs[0];
        mConstructorArgs[0] = context;
        try {
            if (-1 == name.indexOf('.')) {
                view = onCreateView(parent, name, attrs);
            } else {
                view = createView(name, null, attrs);
            }
        } finally {
            mConstructorArgs[0] = lastContext;
        }
    }
    return view;

LayoutInflater 源码 我们讲到 mFactory2、mFactory、mPrivateFactory 全部为 null ,其实并不严谨。因为 Activity 也是一个 Factory2 的实现。

在 Activity 的 attach() 方法调用了

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window) {
    ……
    mWindow.getLayoutInflater().setPrivateFactory(this);
    ……
}

而 BaseFragmentActivityApi14 又一次重载了 Activity 实现的 Factory2. onCreateView 。并拦截 <fragment> 标签交给 FragmentActivity 的 dispatchFragmentsOnCreateView() 方法。

总结一个简单的 UML 图

fragment_02.png

Fragment 执行生命周期

跟随 FragmentActivity 生命周期

在 FragmentActivity 的 onCreate() 中

 protected void onCreate(@Nullable Bundle savedInstanceState) {
    mFragments.attachHost(null /*parent*/);

    super.onCreate(savedInstanceState);
    ……
    mFragments.dispatchCreate();
}

public void dispatchCreate() {
    mHost.mFragmentManager.dispatchCreate();
}

public void dispatchCreate() {
    mStateSaved = false;
    mExecutingActions = true;
    moveToState(Fragment.CREATED, false);
    mExecutingActions = false;
}    

其中 moveToState(Fragment.CREATED, false) 会执行 Fragment 的 onCreate() 方法。

然后在 onStart() 方法中调用 mFragments.dispatchStart() ,执行 Fragment 的 onStart()方法 。

然后在 onResume() 是会调用 mHandler.sendEmptyMessage(MSG_RESUME_PENDING)

final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_REALLY_STOPPED:
                if (mStopped) {
                    doReallyStop(false);
                }
                break;
            case MSG_RESUME_PENDING:
                onResumeFragments();
                mFragments.execPendingActions();
                break;
            default:
                super.handleMessage(msg);
        }
    }

};

接着会执行 onResumeFragments() -> mFragments.dispatchResume() , 执行 Fragment 的 onResume() 方法。

以此类推 Fragment 的生命周期跟随 FragmentActivity 的生命周期依次执行。

在 FragmentActivity 中动态添加 Fragment

在 FragmentActivity 中动态添加 Fragment 需要获得一个 FragmentTransaction

然后通过 FragmentTransaction.replace(R.id.fragment, new xxFragment()) 或者 FragmentTransaction.add(R.id.fragment, new xxFragment()) 添加一个创建的 Fragment 到 FragmentActivity(其实是 FragmentManager)

最后通过 FragmentTransaction.commit() 显示 Fragment。

获得 FragmentTransaction

获得 FragmentTransaction 首先获得 FragmentManager 。

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

mFragments 是一个 FragmentController

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

FragmentController 的所有方法,都是包裹这 HostCallbacks() 来实现的。HostCallbacks 是 FragmentHostCallback 的子类

public FragmentManager getSupportFragmentManager() {
    return mHost.getFragmentManagerImpl();
}

其中 mHost 就是 HostCallbacks 的实例。HostCallbacks 继承 FragmentHostCallback

FragmentManagerImpl getFragmentManagerImpl() {
    return mFragmentManager;
}

在 FragmentHostCallback 中有成员变量

final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();

所以 FragmentTransaction 由 FragmentManagerImpl 创建。FragmentManagerImpl 又是 FragmentManager 的实例。

@Override
public FragmentTransaction beginTransaction() {
    return new BackStackRecord(this);
}

所以最终我们获得的 FragmentTransaction 是一个 BackStackRecord 实例。

获得 FragmentTransaction 的 add() 、replace()

这两个方法都在 BackStackRecord 中 ,有很多 add()、replace() 方法,这里贴两个重要的

@Override
public FragmentTransaction add(int containerViewId, Fragment fragment) {
    doAddOp(containerViewId, fragment, null, OP_ADD);
    return this;
}

@Override
public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
    if (containerViewId == 0) {
        throw new IllegalArgumentException("Must use non-zero containerViewId");
    }

    doAddOp(containerViewId, fragment, tag, OP_REPLACE);
    return this;
}

可以看出无论 add()、replace() 最终都调用 doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) 方法,只是 opcmd 值不同。

最终会添加一个 Op 对象

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
    ……
    addOp(new Op(opcmd, fragment));
}

void addOp(Op op) {
    mOps.add(op);
    op.enterAnim = mEnterAnim;
    op.exitAnim = mExitAnim;
    op.popEnterAnim = mPopEnterAnim;
    op.popExitAnim = mPopExitAnim;
}
获得 FragmentTransaction 的 commit()

commit() 同样在 BackStackRecord 中实现。

@Override
public int commit() {
    return commitInternal(false);
}

然后执行

int commitInternal(boolean allowStateLoss) {
    ……
    mCommitted = true;
    if (mAddToBackStack) {
        mIndex = mManager.allocBackStackIndex(this);
    } else {
        mIndex = -1;
    }
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}

mIndex 是 BackStackRecord 在 FragmentManager 中保存的一个 ArrayList 的位置。

然后执行

public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        checkStateLoss();
    }
    synchronized (this) {
        ……
        scheduleCommit();
    }
}

接着执行

private void scheduleCommit() {
    synchronized (this) {
        boolean postponeReady =
                mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
        boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
        if (postponeReady || pendingReady) {
            mHost.getHandler().removeCallbacks(mExecCommit);
            mHost.getHandler().post(mExecCommit);
        }
    }
}

mExecCommit 是一个 Runnable

Runnable mExecCommit = new Runnable() {
    @Override
    public void run() {
        execPendingActions();
    }
};

然后就快到关键方法

public boolean execPendingActions() {
    ensureExecReady(true);

    boolean didSomething = false;
    while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
        mExecutingActions = true;
        try {
            optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
        } finally {
            cleanupExec();
        }
        didSomething = true;
    }

    doPendingDeferredStart();

    return didSomething;
}

接着执行

private void optimizeAndExecuteOps(ArrayList<BackStackRecord> records,
        ArrayList<Boolean> isRecordPop) {
    ……
    int startIndex = 0;
    for (int recordNum = 0; recordNum < numRecords; recordNum++) {
            ……
            executeOpsTogether(records, isRecordPop, recordNum, optimizeEnd);
            ……
        }
    }
    ……
}

然后到了 executeOpsTogether

private void executeOpsTogether(ArrayList<BackStackRecord> records,
        ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
    ……
    if (!allowOptimization) {
        FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
                false);
    }
    executeOps(records, isRecordPop, startIndex, endIndex);
    ……
}

其中 FragmentTransition.startTransitions 最终会执行 addToFirstInLastOut

然后执行 manager.moveToState(fragment, Fragment.CREATED, 0, 0, false);

在 moveToState 中,会执行 Fragment 的 onAttach() 方法

其中的 executeOps(records, isRecordPop, startIndex, endIndex) 之中执行 void executeOps()

mManager.moveToState(mManager.mCurState, true);

因为此时 Activity 已经是 Resume 状态,所以 mManager.mCurState == RESUMED

然后 mManager.moveToState 会一次执行
Fragment.performCreateView()
Fragment.performActivityCreated()
Fragment.performStart()
Fragment.performResume()

通过上面可以发现 void moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive) 是最关键的方法。Fragment 的各个状态都是通过这个方法进行切换的。

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
        boolean keepActive) {
    ……
    if (f.mState <= newState) { // Fragment 从后台到显示
        ……
        switch (f.mState) {
            case Fragment.INITIALIZING:
                if (newState > Fragment.INITIALIZING) {
                    ……
                    f.onAttach(mHost.getContext());
                    ……
                }

            case Fragment.CREATED:
                ……
                if (newState > Fragment.CREATED) {
                        ……
                        f.mView = f.performCreateView(f.getLayoutInflater(
                                f.mSavedFragmentState), container, f.mSavedFragmentState);
                        ……
                    }

                    f.performActivityCreated(f.mSavedFragmentState);
                    ……
                }
            case Fragment.ACTIVITY_CREATED:
                if (newState > Fragment.ACTIVITY_CREATED) {
                    f.mState = Fragment.STOPPED;
                }
            case Fragment.STOPPED:
                if (newState > Fragment.STOPPED) {
                    if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
                    f.performStart();
                    dispatchOnFragmentStarted(f, false);
                }
            case Fragment.STARTED:
                if (newState > Fragment.STARTED) {
                    if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                    f.performResume();
                    dispatchOnFragmentResumed(f, false);
                    f.mSavedFragmentState = null;
                    f.mSavedViewState = null;
                }
        }
    } else if (f.mState > newState) {// Fragment 从显示到后台
        switch (f.mState) {
            case Fragment.RESUMED:
                if (newState < Fragment.RESUMED) {
                    if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
                    f.performPause();
                    dispatchOnFragmentPaused(f, false);
                }
            case Fragment.STARTED:
                if (newState < Fragment.STARTED) {
                    if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
                    f.performStop();
                    dispatchOnFragmentStopped(f, false);
                }
            case Fragment.STOPPED:
                if (newState < Fragment.STOPPED) {
                    if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
                    f.performReallyStop();
                }
            case Fragment.ACTIVITY_CREATED:
                if (newState < Fragment.ACTIVITY_CREATED) {
                    ……
                    f.performDestroyView();
                    dispatchOnFragmentViewDestroyed(f, false);
                    ……
                }
            case Fragment.CREATED:
                if (newState < Fragment.CREATED) {
                    ……
                }
        }
    }
    ……
}

参考资料

安卓基础:Activity/Fragment 生命周期

上一篇下一篇

猜你喜欢

热点阅读