3

I just started using the architecture component of Android in my app, and I have a use case when:

  • A fragment is an observer of ViewModel's LiveData (which comes from a Room request)
  • This fragment starts an activity at some point
  • The activity needs to use the same data (as LiveData in the fragment) and update it
  • The user then returns to the fragment

I tried using the same ViewModel class and adding the fragment and activity as observers, thinking that somehow updating from the activity will affect the fragment when returning to it, but it doesn't work. The two ViewModels seem independent.

How can I force refresh the fragment data when returning from the activity (in onActivityResult for example)? Or is it possible to share the same ViewModel between the fragment and activity? (though I doubt it since the ViewModel is linked to the lifecycle of the observer)

Fragment

public void onAttach(@NonNull Context context) {
    ...
    mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
    mViewModel.getData().observe(this, new Observer<List<Data>>() {
        @Override
        public void onChanged(List<Data> data) {
            mAdapter.setData(data);
        }
    });
}

// in an onClick method
startActivity(intent); // go to the Activity

Activity

protected void onCreate(Bundle savedInstanceState) {
    ...
    mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
    mViewModel.getData().observe(this, new Observer<List<Data>>() {
        @Override
        public void onChanged(List<Data> data) {
            mPagerAdapter.setData(data);
        }
    });
}

Any help will be appreciated!

EDIT:

View Model

public class MyViewModel extends AndroidViewModel {
    private Dao dao;
    private ExecutorService executorService;

    public MyViewModel (@NonNull Application application) {
        super(application);
        dao = AppDatabase.getInstance(application).getDao();
        executorService = Executors.newSingleThreadExecutor();
    }

    public LiveData<Data> getData() {
        return dao.getAllData();
    }

    // other methods to update and delete with executorService
}
Herve B
  • 195
  • 1
  • 15
  • 1
    Life cycles are individual for each activity or freshmen’s, so your two ViewModels would be completely different lifecycles, id recommend maybe send the data over in an Intent when starting the fragment and pushing it back after you’re done (if you aren’t saving it from inside the fragment, otherwise you could just make another call to the room database) – Brandon Sep 13 '19 at 12:00
  • What you described should work if both activity and fragment use same instance of ViewModel. For this, I use Koin for Dependency Injection. – UrosKekovic Sep 13 '19 at 12:01
  • Post the ViewModel class too please – Ivan Wooll Sep 13 '19 at 12:03
  • You can check this answer: https://stackoverflow.com/questions/44641121/share-viewmodel-between-fragments-that-are-in-different-activity – UrosKekovic Sep 13 '19 at 12:11
  • Post you viewModel class – Muhammad Usman Butt Sep 13 '19 at 12:32
  • @Brandon I can't send the data since it's a `Room `request result in form of `LiveData` I tried doing another call when returning from the activity, but it does nothing... Also, I tried using the `MutableLiveData` but it doesn't work with `Room` – Herve B Sep 13 '19 at 12:41

2 Answers2

2

I managed to get the result you want by seting a common lifecycle owner for the viewmodel, and using the same viewModel at the different fragments. Inside my fragment, i get the view model like this:

INSIDE FRAGMENT:

 var userViewModel = activity?.run{ViewModelProviders.of(this, SharedUserViewModel.MainActivityViewModelFactory(applicationContext))[SharedUserViewModel::class.java]}

Did you see i use the activity as the "ViewModelProviders.of" parameter? This way, the view model have the same owner, its working alright for me.

Thalis Vilela
  • 335
  • 1
  • 10
0

Yes you can share ViewMode between activity and Fragment Using SharedViewModel.