getActivity()和 onAttach(Context context)

    xiaoxiao2022-07-01  139

    getActivity()  和 onAttach(Context context)  之前同事说getActivity()有时候会出现空值现象.解决方法不用getActivity() 采用onAttach(Context context) 自己不是很理解,决定看看源码的区别.

    之前写一片 FragmentManager 加载过程 https://blog.csdn.net/qianxiangsen/article/details/81357579

    这里带大家在回顾下 FragmentManager 是用来管理Fragment 负责 添加 移除 显示 隐藏,FragmentManager 是抽象类她的具体实现类是FragmentManagerImpl 是FragmentManager的内部类

    在FragmentActivity 中调用 getSupportFragmentManager() 来进行fragment 管理,这里我们先看下 FragmentActivity源码如下:

    在FragmentActivity 中调用getSupportFragmentManager() public class FragmentActivity extends BaseFragmentActivityJB { //创建 FragmentController 并 new HostCallbacks()父类就是FragmentHostCallback() final FragmentController mFragments = FragmentController.createController(new HostCallbacks()); //创建createController 并需要传 FragmentHostCallback对象 public static final FragmentController createController(FragmentHostCallback<?> callbacks) { return new FragmentController(callbacks); } // new HostCallbacks() 并通过 super(FragmentActivity.this /*fragmentActivity*/); //将当前FragmentActivity.this 传给FragmentHostCallback class HostCallbacks extends FragmentHostCallback<FragmentActivity> { public HostCallbacks() { super(FragmentActivity.this /*fragmentActivity*/); } } //通过 super(FragmentActivity.this /*fragmentActivity*/) FragmentHostCallback(FragmentActivity activity) { this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/); } //mActivity 赋值 //mContext activity强转Context //mHandler 获取activity.mHandler FragmentHostCallback(Activity activity, Context context, Handler handler, int windowAnimations) { mActivity = activity; mContext = context; mHandler = handler; mWindowAnimations = windowAnimations; } //mHost 是 FragmentHostCallback 调用 FragmentHostCallback.getFragmentManagerImpl() public FragmentManager getSupportFragmentManager() { return mHost.getFragmentManagerImpl(); }

    这里我们看到FragmentActivity 启动完成后会创建FragmentController.createController(new HostCallbacks()) 并需要传HostCallbacks()是继承FragmentHostCallback()通过 super(FragmentActivity.this /*fragmentActivity*/) 将FragmentActivity.this传给FragmentHostCallback() 并执行四个参数的构造方法 分别给mActivity 赋值,将mActivity强转 mContext并赋值mContext,获取mActivity的mHandler并赋值给mHandler,第四个参数是0

    这里我先将 FragmentActivity.this 传递给FragmentHostCallback ,我们先记住,接下来我们看下getActivity()

    @Nullable public final FragmentActivity getActivity() { return this.mHost == null ? null : (FragmentActivity)this.mHost.getActivity(); } 这里的 mHost 就是 FragmentHostCallback mHost; 上面说到FragmentActivity 创建时候创建FragmentHostCallback 并将 FragmentActivity.this 传递给FragmentHostCallback ,所以说FragmentActivity不销毁 mHost就不会为空,我们在看下 .mHost.getActivity() @Nullable Activity getActivity() { return this.mActivity; }

    这里直接调用 this.mActivity,看下这个mActivity是哪里来的

    @Nullable private final Activity mActivity; FragmentHostCallback(@Nullable Activity activity, @NonNull Context context, @NonNull Handler handler, int windowAnimations) { this.mFragmentManager = new FragmentManagerImpl(); this.mActivity = activity; this.mContext = (Context)Preconditions.checkNotNull(context, "context == null"); this.mHandler = (Handler)Preconditions.checkNotNull(handler, "handler == null"); this.mWindowAnimations = windowAnimations; }

    看到了把 ,上面说到FragmentActivity 创建时候创建FragmentHostCallback 并将 FragmentActivity.this 传递给FragmentHostCallback,所以说这个activty ,就是创建FragmentActivity,只要FragmentActivity不销毁 ,getActivity 就不会我空.

    onAttach(Context context);

    接下来我们在看下 onAttach(Context context)  这个Context 是怎么来的

    之前写一片 FragmentManager 加载过程 https://blog.csdn.net/qianxiangsen/article/details/81357579

    这里讲到了怎么加载onAttach(Context context) 方法 ,只有在 commit 提交时候才会去加载Fragment 

    执行 this.mManager.enqueueAction(this, allowStateLoss); 调用到 moveToState ,moveToState才会去调用fragment 生命周期方法

    void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { switch(f.mState) { case 0: f.mHost = this.mHost; f.mParentFragment = this.mParent; f.mFragmentManager = this.mParent != null ? this.mParent.mChildFragmentManager : this.mHost.getFragmentManagerImpl(); f.onAttach(this.mHost.getContext()); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()"); } if (newState > 3) { if (DEBUG) { Log.v("FragmentManager", "moveto RESUMED: " + f); } f.performResume(); this.dispatchOnFragmentResumed(f, false); f.mSavedFragmentState = null; f.mSavedViewState = null; } } } else if (f.mState > newState) { switch(f.mState) { case 4: if (newState < 4) { if (DEBUG) { Log.v("FragmentManager", "movefrom RESUMED: " + f); } f.performPause(); this.dispatchOnFragmentPaused(f, false); } case 3: if (newState < 3) { if (DEBUG) { Log.v("FragmentManager", "movefrom STARTED: " + f); } f.performStop(); this.dispatchOnFragmentStopped(f, false); } case 2: if (newState < 2) { if (DEBUG) { Log.v("FragmentManager", "movefrom ACTIVITY_CREATED: " + f); } if (f.mView != null && this.mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) { this.saveFragmentViewState(f); } f.performDestroyView(); f.mInLayout = false; } case 1: if (newState < 1) { if (this.mDestroyed) { if (f.getAnimatingAway() != null) { View v = f.getAnimatingAway(); f.setAnimatingAway((View)null); v.clearAnimation(); } else if (f.getAnimator() != null) { Animator animator = f.getAnimator(); f.setAnimator((Animator)null); animator.cancel(); } } if (f.getAnimatingAway() == null && f.getAnimator() == null) { if (DEBUG) { Log.v("FragmentManager", "movefrom CREATED: " + f); } if (!f.mRetaining) { f.performDestroy(); this.dispatchOnFragmentDestroyed(f, false); } else { f.mState = 0; } f.performDetach(); this.dispatchOnFragmentDetached(f, false); if (!keepActive) { if (!f.mRetaining) { this.makeInactive(f); } else { f.mHost = null; f.mParentFragment = null; f.mFragmentManager = null; } } } else { f.setStateAfterAnimating(newState); newState = 1; } } } } } } 调用moveToState 方法 我看到调用onAttach方法 f.onAttach(this.mHost.getContext()); 我们还看到我们熟悉 mHost ,这个 mHost 跟getActivity() 的mHost 是同一个 ,只是他调用的是.mHost.getContext() 上面说了mHost.getContext()这个 context 也是 FragmentActivity 将Activity强转的context @NonNull Context getContext() { return this.mContext; } FragmentHostCallback(@Nullable Activity activity, @NonNull Context context, @NonNull Handler handler, int windowAnimations) { this.mFragmentManager = new FragmentManagerImpl(); this.mActivity = activity; this.mContext = (Context)Preconditions.checkNotNull(context, "context == null"); this.mHandler = (Handler)Preconditions.checkNotNull(handler, "handler == null"); this.mWindowAnimations = windowAnimations; }

    所以说这 getActivity() 还是onAttach(Contrext context) 的context 都是FragmentActivity 只要FragmentActivity 不销毁,这两个值都不会为空

    最新回复(0)