1、结论
子线程上可以添加,但最终还是抛到了主线程执行
2、分析
- 添加
Fragment都会调用FragmentTransaction里面的方法,并最终调用commit()方法。该方法是一个抽象方法,其实现类是BackStackRecord,并最终调用到FragmentManagerImpl类的scheduleCommit()方法
void scheduleCommit() {
synchronized(this) {
boolean postponeReady = this.mPostponedTransactions != null && !this.mPostponedTransactions.isEmpty();
boolean pendingReady = this.mPendingActions != null && this.mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
this.mHost.getHandler().removeCallbacks(this.mExecCommit);
this.mHost.getHandler().post(this.mExecCommit); //切换host所在的线程
this.updateOnBackPressedCallbackEnabled();
}
}
}
可以看到在方法内部使用了Handler,那是不是切换到了主线程呢?我们看一下这个handler在哪里赋值的。
- 该
Handler在FragmentManagerImpl类的attachController()方法内赋值:
public void attachController(@NonNull FragmentHostCallback host, @NonNull FragmentContainer container, @Nullable Fragment parent) {
if (this.mHost != null) {
throw new IllegalStateException("Already attached");
} else {
this.mHost = host; //这里给host赋值
this.mContainer = container;
this.mParent = parent;
if (this.mParent != null) {
this.updateOnBackPressedCallbackEnabled();
}
if (host instanceof OnBackPressedDispatcherOwner) {
OnBackPressedDispatcherOwner dispatcherOwner = (OnBackPressedDispatcherOwner)host;
this.mOnBackPressedDispatcher = dispatcherOwner.getOnBackPressedDispatcher();
LifecycleOwner owner = parent != null ? parent : dispatcherOwner;
this.mOnBackPressedDispatcher.addCallback((LifecycleOwner)owner, this.mOnBackPressedCallback);
}
if (parent != null) {
this.mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
} else if (host instanceof ViewModelStoreOwner) {
ViewModelStore viewModelStore = ((ViewModelStoreOwner)host).getViewModelStore();
this.mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
} else {
this.mNonConfig = new FragmentManagerViewModel(false);
}
}
}
- 其调用方为
FragmentController类的attachHost方法:
public void attachHost(@Nullable Fragment parent) {
this.mHost.mFragmentManager.attachController(this.mHost, this.mHost, parent);
}
所以切换线程的Handler是在FragmentController类中的成员变量mHost赋值的。而mHost是在构造方法中赋值的。
private FragmentController(FragmentHostCallback<?> callbacks) {
this.mHost = callbacks;
}
- 在FragmentActivity中调用了构造方法
final FragmentController mFragments = FragmentController.createController(new FragmentActivity.HostCallbacks());
所以切换线程用到的Handler是在FragmentActivity中创建的
- 而
Activity是在主线程创建的,所以该Handler使用的是主线程的Looper,所以在子线程添加Fragment时,会抛到主线程执行
3、问题
可以在子线程显示DialogFragment吗?