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
吗?