Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caused by java.lang.IllegalStateException: Can't create ViewModelProvider for detached fragment

I need some help to ressolve the following crash. I am refreshing my list on Restart in Activity by calling fragment in viewpager to refresh its list. Following is the stacktrace of the crash:

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)

call from activity onRestart :

((MyListFragment) adapter.getFragmentAtPosition(0)).search("");

method in fragment :

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);
    }
like image 840
Sohail Ahmad Khan Avatar asked May 09 '18 06:05

Sohail Ahmad Khan


2 Answers

Since the error is that the fragment is not attached yet, it needs to be done when we are sure the fragment is actually attached. Its a good way of doing this; by putting the code inside the override method onAttach

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    myListViewModel = ViewModelProviders.of(this, viewModelFactory).get(MyListViewModel.class);
}
like image 150
Otziii Avatar answered Oct 19 '22 23:10

Otziii


If you're using a viewpager, be sure that the corresponding fragment is actually attached to its activity (this is what the error tries to tell you). It might happen that the fragment is not visible, thus it's not attached (depending on how the view pager was configured).

a quick&dirty fix:

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);
}

However, you should re-investigate in your architecture, because those checks often imply some other code smells. When you're working with the new Android Architecture Patterns, there should be no need of this check as the lifecycle pattern handles all this for you: https://developer.android.com/topic/libraries/architecture/lifecycle

So, basically, you should not directly call any function of a fragment directly, instead call the corresponding business logic, which notifies the fragment to update its views.

like image 33
Denis Loh Avatar answered Oct 20 '22 01:10

Denis Loh