• Fragment中getContext得到的context从哪来?


    我们先看下fragment的getContext方法:

        @Nullable
        public Context getContext() {
            return mHost == null ? null : mHost.getContext();
        }
    

    可以看到context是由mHost的getContext方法得到的,Ctrl+左键发现mHost是一个FragmentHostCallback类的对象,接下来就是要知道Fragment中的mHost对象是在哪里赋值的就行了。

    我们的fragment一般是通过fragmentManager的beginTransaction方法得到FragmentTransaction然后add添加,而我们getSupportFragmentManager获取到的是FragmentManagerImpl,也就是FragmentManager的实现类(后面会知道),我们看FragmentManagerImpl的beginTransaction方法:

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

    可以看到我们得到的FragmentTransaction是一个BackStackRecord对象,该类继承自FragmnetTransaction,而BackStackRecord的add方法最终还是回到FragmentManagerImpl的addFragment方法(这其中涉及到fragment的启动过程,这里不细讲):

    public void addFragment(Fragment fragment, boolean moveToStateNow) {
           ...
                if (moveToStateNow) {
                    moveToState(fragment);
    }
    void moveToState(Fragment f) {
            moveToState(f, mCurState, 0, 0, false);
    }
    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                boolean keepActive) {
    ...
    switch (f.mState) {
                    case Fragment.INITIALIZING:
                        ...
                            f.mHost = mHost;
                            f.mParentFragment = mParent;
                            f.mFragmentManager = mParent != null
                                    ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
     
                           ...
                        }
    }
    

    可以看到 f.mHost = mHost ,也就是fragment中获取context时使用的FragmentHostCallback类的对象mHost是由FragmentManagerImpl赋值的。

    那我们的问题就变成了:它的mHost哪里来的?

    我们看到fragmentManagerImpl的attachController方法:

    public void attachController(FragmentHostCallback host,
                FragmentContainer container, Fragment parent) {
            if (mHost != null) throw new IllegalStateException("Already attached");
            mHost = host;
            mContainer = container;
            mParent = parent;
    }
    

    mHost是在这里赋值,该方法由FragmentController调用:

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

    那fragmentController是谁?它的mHost是哪里来的?

    我们添加Fragment一般是通过getSupportFragmentManager().beginTransaction()得到一个FragmentTransaction对象,我们看一下FragmentActivity中的getSupportFragmentManager方法:

    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
    ...
        public FragmentManager getSupportFragmentManager() {
            return mFragments.getSupportFragmentManager();
        }
    

    可以看到Activity是通过一个final类型的FragmentController对象的getSupportFragmentManager来获取fragmentManager的

    public class FragmentController {
        private final FragmentHostCallback<?> mHost;
     
        /**
         * Returns a {@link FragmentController}.
         */
        public static FragmentController createController(FragmentHostCallback<?> callbacks) {
            return new FragmentController(callbacks);
        }
     
        private FragmentController(FragmentHostCallback<?> callbacks) {
            mHost = callbacks;
        }
     
        /**
         * Returns a {@link FragmentManager} for this controller.
         */
        public FragmentManager getSupportFragmentManager() {
            return mHost.getFragmentManagerImpl();
        }
    ...
    }
    

    FragmentController的getSupportFragmentManager是通过构造函数的参数FragmentHostCallback对象的getFragmentMnaagerIml得到:

    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();
        ...
        FragmentManagerImpl getFragmentManagerImpl() {
            return mFragmentManager;
        }
    }
    

    直接返回一个FragmentManagerImpl,它继承自FragmentManager。

    原来fragmentManager和其mHost对象都是由FragmentActivity中的fragmentController对象得到,

    到这里我们的问题变成了:FragmentController中的mHost是哪来的?

    就是FragmentActivity传入的:

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

    我们看一下HostCallbacks:

    class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
            public HostCallbacks() {
                super(FragmentActivity.this /*fragmentActivity*/);
            }
    }
    

    可以看到HostCallbacks持有一个当前的activity对象,调用FragmentHostCallback的构造函数:

    public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
            this(context instanceof Activity ? (Activity) context : null, 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;
        }
    

    一切都付出水面了,mHost中的context在这里。

    总结一下:

    FragmentActivity有一个final类型的FragmentController对象,FragmentController持有HostCallback对象mHost(mHost持有context),然后FragmentManager也是由该mHost创建并在FragmentController调用其attachController方法时候为其mHost赋值(FragmentManager的mHost和FragmentController的mHost是同一个),Fragment中的mHost在add的时候被FragmentManager赋值。

    其实一切的来源都是FragmentActivity持有的FragmentController对象!

    虽然可能用脚指头想都能想到fragment的getContext方法获取的就是其附着的Activity,但是还是写了。。。

  • 相关阅读:
    springboot 上传文件过大的500异常
    java OSS批量下载,并压缩为ZIP
    Java 对象转xml (dom 4j)
    windows 10 64位机器上 安装部署
    Java 读取excel 文件流
    关于Java 去除空格,换行的代码
    ORACLE 查询近一天,近半小时内的数据
    【转】C#(ASP.Net)获取当前路径的方法集合
    【转】NumPy-快速处理数据
    【转】Eclipse 常用快捷键 (动画讲解)
  • 原文地址:https://www.cnblogs.com/sishuiliuyun/p/14296425.html
Copyright © 2020-2023  润新知