本文共 5699 字,大约阅读时间需要 18 分钟。
对于Fragment,相信做过android的肯定或多或少的都用过,但是你对它的实现原理是否知道,这里我们就从一个大的方向来看看它是如何设计的。
Fragment是有生命周期的,和Activity类似,我们可以把fragment看成是activity的一部分,fragment的生命周期其实就是由activity来控制的,只不过fragment内部又做了一些细致的划分,这也就是为什么我们会在fragment中多出一些方法的回调,这里有一个点需要注意,activity并不是直接控制fragment的,他们中间隔着一个FragmentManager,那这个FragmentManager又是什么呢?我们可以理解为是一个可以感知activity生命周期的,负责管理fragment的类,它里面有一个集合就是负责收集添加进activity的fragment,也就是ArrayList,我们知道,在fragment中能做一些只能在activity中做的事情,这个又是怎么实现的呢?这个用到的就是回调了,涉及到的一个抽象类是FragmentHostCallback,这个类在FragmentActivity中有实现,当在fragment中使用调用startActivity()时,其实最终调用到的还是Activity中startActivity(),下面就从源码中来看看,主要是看流程,不会涉及到细节。 先来看下FragmentActivity中定义的一个成员变量:final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
这里涉及到两个类:
1、FragmentController :主要作用是Activity到Fragment通信; 2、HostCallbacks:主要作用是Fragment到Activity通信,它继承自FragmentHostCallback; 这里先来看下HostCallbacks的构造方法:class HostCallbacks extends FragmentHostCallback{ public HostCallbacks() { super(FragmentActivity.this /*fragmentActivity*/); } ... }
又调用了父类的构造方法,并将FragmentActivity传进去,跟着往下走:
public abstract class FragmentHostCallbackextends FragmentContainer { private final Activity mActivity; final Context mContext; private final Handler mHandler; final int mWindowAnimations; final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl(); private SimpleArrayMap mAllLoaderManagers; private LoaderManagerImpl mLoaderManager; private boolean mCheckedForLoaderManager; private boolean mLoadersStarted; public FragmentHostCallback(Context context, Handler handler, int windowAnimations) { this(null /*activity*/, context, handler, windowAnimations); } 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; } public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { if (requestCode != -1) { throw new IllegalStateException( "Starting activity with a requestCode requires a FragmentActivity host"); } mContext.startActivity(intent); } ... }
可以看到这里将activity和handler保存了起来,这样当Fragment中有需要执行Fctivity的方法时,就可以通过这个保存的变量来实现了,比如,当在fragment中调用startActivity()时,最后调用到的就是这里的onStartActivityFromFragment(),还有其他一些Fragment回调到Activity的方法都是定义在这里。这里有一个需要特别注意的属性mFragmentManager ,它就是管理Fragment的,activity涉及到对fragment的操作都是通过他来实现的,比如activity对fragment生命周期分发。
在来FragmentActivity的各个生命周期方法中可以发现,都会使用到mFragments,这里以FragmentActivity的onCreate()方法为例,来看下他对mFragments的使用:@Override protected void onCreate(@Nullable Bundle savedInstanceState) { mFragments.attachHost(null /*parent*/); super.onCreate(savedInstanceState); //以下部分是对Fragment状态的恢复,想进一步了解的可以看下上一篇: Fragment之setRetainInstance详解 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); } //Fragment将会执行对应的生命周期方法,其他的生命周期类似,这里就不一一去看了 mFragments.dispatchCreate(); }
可以看到这里全是对Fragment的处理,其中mFragments.dispatchCreate()是分发对应的生命周期,fragment中的生命周期都是以这种方式分发下去的,这也就是fragment和activity的生命周期是对应的,这里在主要来看下mFragments.attachHost(null /parent/),看下它里面做了些什么:
public class FragmentController { private final FragmentHostCallback mHost; public static final FragmentController createController(FragmentHostCallback callbacks) { return new FragmentController(callbacks); } private FragmentController(FragmentHostCallback callbacks) { mHost = callbacks; } public FragmentManager getSupportFragmentManager() { return mHost.getFragmentManagerImpl(); } public LoaderManager getSupportLoaderManager() { return mHost.getLoaderManagerImpl(); } public void attachHost(Fragment parent) { mHost.mFragmentManager.attachController( mHost, mHost /*container*/, parent); } ...}
先看下它的构造方法,将HostCallbacks 对象保存到了mHost中,再来看下它的attacHost()方法,使用到了mFragmentManager,它是在FragmentHostCallback中实例化的,上面也有提到,它是一个FragmentManagerImpl对象,跟着attachController()这个方法进去看看:
final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory { ... FragmentHostCallback mHost; FragmentContainer mContainer; Fragment mParent; public void attachController(FragmentHostCallback host, FragmentContainer container, Fragment parent) { if (mHost != null) throw new IllegalStateException("Already attached"); mHost = host; mContainer = container; mParent = parent; } ....}
也没什么,就是初始化一些变量,这里注意这个mHost,当在fragment需要调回到activity时,用到的就是mHost(也就是FragmentHostCallback),到这里,对于FragmentManager的准备工作就算是完成了,接下开就是使用了,下一篇再来介绍fragment的工作流程。
#总结 1、链接Activity和Fragment的点是FragmentHostCallback; 2、Fragment向Activity通信通过FragmentHostCallback定义的方法进行回调; 3、FragmentHostCallback中实例化了FragmentManagerImpl ,管理着所有添加的Fragment的,Activity向Fragment通信就是通过他来实现的; 4、为了剥离Activity向Fragment的通信,使用FragmentController 对FragmentManagerImpl 进行代理,这样就可以使用FragmentController 对Fragment进行通信了。转载地址:http://xkhai.baihongyu.com/