qingmei2/MVI-Architecture

快速点击底部按钮的情况下,ReposFragment的render方法会在onDestroyView方法之后调用,导致render方法内引用mSwipeRefreshLayout等view报空指针异常

7-cat opened this issue · 5 comments

7-cat commented
    mViewModel.states()
        .observeOn(mSchedulerProvider.ui())
        .autoDisposable(scopeProvider)
        .subscribe(this::render)

这个autoDisposable可以设置在onDestroyView就解除订阅吗?

7-cat commented

uber/AutoDispose#192

目前我只能在render方法内加上
if(view==null){
return
}

很神奇的bug,我似乎没有复现.

我看了一下Fragment的源码, 结束订阅的事件确实应该在 Fragment.onDestroyView()前就发射了:

    void performDestroyView() {
        if (mView != null) {
            mViewLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
        }
     //...
        onDestroyView();
     //...
    }

我不清楚你是如何使用的,因为你好像描述过,你是使用Navigation对主页进行的Tab切换控制,这种情况下Tab的Fragment会被销毁掉?

7-cat commented

我是使用原生的Navigation对主页进行的Tab切换控制,切换Tab确实会销毁和重建Tab里面的fragment,在主页的Tab里面我又装了一个ViewPager,然后在ViewPager的每个页面里面放的是和ReposFragment一样的fragment,唯一不同的是我将childFragmentManager传入的adapter。
如果快速点击Navigation的主页tab,就会出现这个bug。。

oldergod/android-architecture#44
和这个可能有点像

@7-cat

我看到了你在这个 issue中的建议,个人感觉,这只是治标而不是治本。

根本原因还是Fragment的生命周期,我会抽时间研究一下这个问题,就像 #4 一样,看看能不能得出什么好一点的解决方案。

@7-cat

如果有时间,你能给Fragment的生命周期进行打印吗?

我刚刚看了看FragmentNavigator的源码, 内部是通过replace()函数对Fragment进行导航,但是和BottomNavigationBar配合就不知道怎么执行的了。

calling detach on a fragment inside a fragmentTransaction actually triggers only onDestroyView without triggering onDestroy

我认为这个完全有可能,如果只是调用Fragment#detach而导致没有执行onDestroy()(执行了onDestroyView()),这样ViewModel就不会被执行onClear()

class Fragment {
    // ...
    public void onDestroy() {
        //...
        if (mViewModelStore != null && !isChangingConfigurations) {
            mViewModelStore.clear();   // 即ViewModel.clear()
        }
    }
}

这种情况下,各种异常都有可能出现了......

感觉你这种情况还是Navigation原生的坑...