[Android]可以在子線程添加Fragment嗎?

1、結(jié)論

子線程上可以添加,但最終還是拋到了主線程執(zhí)行

2、分析

  1. 添加Fragment都會(huì)調(diào)用FragmentTransaction里面的方法,并最終調(diào)用commit()方法。該方法是一個(gè)抽象方法,其實(shí)現(xiàn)類是BackStackRecord,并最終調(diào)用到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();
            }

        }
    }

可以看到在方法內(nèi)部使用了Handler,那是不是切換到了主線程呢?我們看一下這個(gè)handler在哪里賦值的。

  1. HandlerFragmentManagerImpl類的attachController()方法內(nèi)賦值:
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. 其調(diào)用方為FragmentController類的attachHost方法:
public void attachHost(@Nullable Fragment parent) {
        this.mHost.mFragmentManager.attachController(this.mHost, this.mHost, parent);
    }

所以切換線程的Handler是在FragmentController類中的成員變量mHost賦值的。而mHost是在構(gòu)造方法中賦值的。

 private FragmentController(FragmentHostCallback<?> callbacks) {
        this.mHost = callbacks;
 }
  1. 在FragmentActivity中調(diào)用了構(gòu)造方法
final FragmentController mFragments = FragmentController.createController(new FragmentActivity.HostCallbacks());

所以切換線程用到的Handler是在FragmentActivity中創(chuàng)建的

  1. Activity是在主線程創(chuàng)建的,所以該Handler使用的是主線程的Looper,所以在子線程添加Fragment時(shí),會(huì)拋到主線程執(zhí)行

3、問題

可以在子線程顯示DialogFragment嗎?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容