[Android]可以在子线程添加Fragment吗?

1、结论

子线程上可以添加,但最终还是抛到了主线程执行

2、分析

  1. 添加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在哪里赋值的。

  1. HandlerFragmentManagerImpl类的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);
            }

        }
    }
  1. 其调用方为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;
 }
  1. 在FragmentActivity中调用了构造方法
final FragmentController mFragments = FragmentController.createController(new FragmentActivity.HostCallbacks());

所以切换线程用到的Handler是在FragmentActivity中创建的

  1. Activity是在主线程创建的,所以该Handler使用的是主线程的Looper,所以在子线程添加Fragment时,会抛到主线程执行

3、问题

可以在子线程显示DialogFragment吗?

你可能感兴趣的:([Android]可以在子线程添加Fragment吗?)