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,但是还是写了。。。

posted @ 2021-01-19 10:00  似水流云  阅读(304)  评论(0编辑  收藏  举报