美文网首页
[Android]可以在子线程添加Fragment吗?

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

作者: 黑森林中的小木屋 | 来源:发表于2022-11-01 10:54 被阅读0次

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

          本文链接:https://www.haomeiwen.com/subject/ucsrtdtx.html