getActivity() 和 onAttach(Context context)

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 不销毁,这两个值都不会为空

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值