Fragment之设计思路

对于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<FragmentActivity> {
		public HostCallbacks() {
	          super(FragmentActivity.this /*fragmentActivity*/);
	    }
	    ...
	}

又调用了父类的构造方法,并将FragmentActivity传进去,跟着往下走:

	public abstract class FragmentHostCallback<E> extends FragmentContainer {
	    private final Activity mActivity;
	    final Context mContext;
	    private final Handler mHandler;
	    final int mWindowAnimations;
	    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
	    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);
	    }
	
	    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进行通信了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值