由java.lang.IllegalStateException引起:无法为分离的片段创建ViewModelProvider

时间:2018-05-09 06:27:32

标签: android android-viewpager fragment

我需要一些帮助来解决以下崩溃问题。我通过调用Activity中的fragment刷新其列表,在viewpager重新启动时刷新了我的列表。以下是崩溃的堆栈跟踪:

Caused by java.lang.IllegalStateException: Can't create ViewModelProvider for detached fragment
       at android.arch.lifecycle.ViewModelProviders.checkActivity(ViewModelProviders.java:51)
       at android.arch.lifecycle.ViewModelProviders.of(ViewModelProviders.java:105)
       at com.ui.fragments.mainpagerfragments.ConversationListFragment.searchConversation(ConversationListFragment.java:383)
       at com.ui.activities.HomeActivity.onRestart(HomeActivity.java:288)
       at android.app.Instrumentation.callActivityOnRestart(Instrumentation.java:1256)
       at android.app.Activity.performRestart(Activity.java:6365)
       at android.app.Activity.performResume(Activity.java:6376)
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3299)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3345)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1532)
       at android.os.Handler.dispatchMessage(Handler.java:111)
       at android.os.Looper.loop(Looper.java:207)
       at android.app.ActivityThread.main(ActivityThread.java:5728)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)

来自活动onRestart的电话:

((MyListFragment) adapter.getFragmentAtPosition(0)).search("");
片段中的

方法:

public void search(String query) {

        query = "%" + query + "%";
        if (myListViewModel == null) {
            myListViewModel = ViewModelProviders.of(this, viewModelFactory).get(MyListViewModel.class);
        }
        if (myListViewModel.mList != null && myListViewModel.mList.hasActiveObservers()) {
            myListViewModel.mList.removeObservers(this);
        }
        myListViewModel.getFilteredList(query).observe(this, mainObserver);
    }

2 个答案:

答案 0 :(得分:2)

由于错误是尚未附加该片段,因此当我们确定该片段已实际附加时,需要完成此操作。这是这样做的好方法;通过将代码放在替代方法 onAttach

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    myListViewModel = ViewModelProviders.of(this, viewModelFactory).get(MyListViewModel.class);
}

答案 1 :(得分:0)

如果您正在使用viewpager,请确保相应的片段实际附加到其活动(这是错误尝试告诉您的内容)。可能会发生片段不可见,因此它没有附加(取决于视图寻呼机的配置方式)。

快速而肮脏的修复:

public void search(String query) {

    if(!isAdded()) return; //<---- returns if the fragment is not attached

    query = "%" + query + "%";
    if (myListViewModel == null) {
        myListViewModel = ViewModelProviders.of(this, viewModelFactory).get(MyListViewModel.class);
    }
    if (myListViewModel.mList != null && myListViewModel.mList.hasActiveObservers()) {
        myListViewModel.mList.removeObservers(this);
    }
    myListViewModel.getFilteredList(query).observe(this, mainObserver);
}

但是,您应该在您的架构中重新调查,因为这些检查通常意味着其他一些代码气味。当您使用新的Android架构模式时,应该不需要此检查,因为生命周期模式会为您处理所有这些:https://developer.android.com/topic/libraries/architecture/lifecycle

所以,基本上,你不应该直接调用片段的任何函数,而是调用相应的业务逻辑,通知片段更新其视图。