Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ViewModel doesn't survive fragment change

I've been trying to share information between fragments using viewmodel's and livedata's.

But when I change from first fragment to another it seems that my viewmodel is reinitialized, making me lose all my previously stored data.

I get both times my viewmodel the same way in my fragments :

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    interventionViewModel = ViewModelProviders.of(this).get(InterventionsViewModel.class);

}

And this is how I replace my framgents in my activity (I guess the problem must come from the fragments lifecycles but I can't figure out where is the error :/)

public void showFragment(Fragment fragment) {

    String TAG = fragment.getClass().getSimpleName();
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_container, fragment, TAG);
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commitAllowingStateLoss();
}

public void backstackFragment() {
    Log.d("Stack count", getSupportFragmentManager().getBackStackEntryCount() + "");
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        finish();
    }
    getSupportFragmentManager().popBackStack();
    removeCurrentFragment();
}

private void removeCurrentFragment() {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    Fragment currentFrag = getSupportFragmentManager()
            .findFragmentById(R.id.fragment_container);

    if (currentFrag != null) {
        transaction.remove(currentFrag);
    }
    transaction.commitAllowingStateLoss();
}

When I need a fragment I call backStackFragment() to remove current fragment then I call showFragment(MyFragment.newInstance());

The fragment are the ones generated by AndroidStudio

Thanks for your help,

Cordially, Matthieu

like image 911
Matthieu Meunier Avatar asked Mar 21 '18 09:03

Matthieu Meunier


People also ask

Does ViewModel survive configuration changes?

The Android team introduced ViewModel and LiveData classes to help save state during configuration changes. A ViewModel stores and manages UI-related data in a lifecycle-conscious manner. Simply put, it allows data to survive configuration changes.

Is ViewModel destroyed when fragment is destroyed?

A ViewModel is always created in association with a scope (an fragment or an activity) and will be retained as long as the scope is alive.

How does a ViewModel retain itself?

ViewModel objects are automatically retained during configuration changes so that data they hold is immediately available to the next activity or fragment instance. FYI: You can use ViewModel to preserve UI state only during a configuration change, nothing else as explained perfectly in this official doc.

Can two fragments use same ViewModel?

In android, we can use ViewModel to share data between various fragments or activities by sharing the same ViewModel among all the fragments and they can access everything defined in the ViewModel. This is one way to have communication between fragments or activities.


2 Answers

Try binding to the activity instead of the current fragment.

interventionViewModel = ViewModelProviders.of(activity).get(InterventionsViewModel.class);
like image 94
Algar Avatar answered Oct 06 '22 00:10

Algar


Since the ViewModelProviders class is deprecated the correct way is to use ViewModelProvider and let the ViewModel survive the fragments life-cycle by binding it to the activities life-cycle by using

requireActivity()

as documented by Google here:

model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
like image 30
Bruno Bieri Avatar answered Oct 05 '22 23:10

Bruno Bieri