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