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);
}
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);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With