Reputation: 7360
So, I have just started experimenting with LiveData
- I am busy with a new project, where I am using ViewModel
as well as LiveData
- with some of the RESTFul
services I use to fetch data, they take no parameters and return some data.
A typical setup of the MVVM paradigm with LiveData
looks much like this:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
Now when we leave this activity, and go to a new activity, by using an Intent or some other means, and not pressing the back button (So, finalize
is not called) - and then come back to MyActivity
- we of course don't fetch the users
again, as we should still have that data.
However, what if we did want to fetch them again?
The only way to do this properly, from what I have looked at, seems to call "setValue" on the getUsers()
LiveData
object
Something like this:
public class MyActivity extends AppCompatActivity {
public void onResume() {
viewModel.setActive(true);
}
}
And the ViewModel
would look like this:
private final MutableLiveData<Boolean> activeLiveData = new MutableLiveData<>();
ViewModel(ViewModelRepo repo){
this.repo = repo;
results = Transformations.switchMap(activeLiveData, active ->{
if(active){
return repo.getUsers();
}else {
return AbsentLiveData.create(); //"Null live data"
}
});
}
LiveData<Users>> getUsers() {
return results;
}
//This could be called "update" with no params
void setActive(boolean active) {
activeLiveData.setValue(active);
}
The one reason I have decided to do it like this is because Google does not want us doing this:
class MyViewModel extends ViewModel {
private final PostalCodeRepository repository;
public MyViewModel(PostalCodeRepository repository) {
this.repository = repository;
}
private LiveData<String> getPostalCode(String address) {
// DON'T DO THIS
return repository.getPostCode(address);
}
}
For this reason:
If this is the implementation, the UI would need to unregister from the previous LiveData and re-register to the new instance each time they call getPostalCode(). Moreover, if the UI is re-created, it triggers another call to repository.getPostCode() instead of using the previous call’s result.
Is there a better way to get the ViewModel
to "redo" its repo.getUsers()
call? Perhaps I could just make a method that says "Update()" instead of "active" but still - its doing the same thing differently.
Upvotes: 1
Views: 1243
Reputation: 5287
Well here you're doing the fetching in the creator of the ViewModel, which locks things in place. Usually they'd advise to fetch the data in the getter, if the data is not there already.
So a good option would be to use the regular pattern first :
private MutableLiveData<Users> users = null;
ViewModel(ViewModelRepo repo){
this.repo = repo;
}
LiveData<Users> getUsers() {
if (users = null) {
fetchUsers();
}
return users;
}
public void fetchUsers() {
users.postValue(repo.getUsers());
}
And then from your Activity/Fragment, whenever you feel necessary to "refresh the users", you'd simply call viewModel.fetchUsers();
Upvotes: 3