问题
I'm currently refactoring my code to include ViewModel with LiveData provided by android.arch library. I have a simple activity that sends request for a password change to server and acts according to HTTP response code.
For that purpose I have created class that extends ViewModel for data and a repository class to call server. My ViewModel class has one MutableLiveData field which I'm subscribing to from my activity using .observe(...) method. The issue is that code inside .observe(...) fires all the time after configuration changes (i.e. screen rotation) and I have no idea why.
Here is the code of ViewModel, Repository and Activity classes accordingly:
ChangePasswordViewModel
public class ChangePasswordViewModel extends ViewModel{
private MutableLiveData<Integer> responseCode;
private PasswordChangeRepository passwordChangeRepository;
public ChangePasswordViewModel() {
responseCode = new MutableLiveData<>();
passwordChangeRepository = new PasswordChangeRepositoryImpl();
}
public MutableLiveData<Integer> responseCodeLiveData() {
return responseCode;
}
public void sendChangePasswordRequest(String newPassword){
passwordChangeRepository.changePassword(newPassword, passChangeCallback());
}
// Callback that fires after server sends a response
private Callback passChangeCallback(){
...
responseCode.postValue(serverResponse)
...
}
PasswordChangeRepository
public class PasswordChangeRepositoryImpl {
public void changePassword(String newPassword, Callback<Void> callback){
//Sending new password to server and processing response in callback
ServerCalls.changePassword(newPassword, callback);
}
}
Activity
public class ChangePasswordActivity extends AppCompatActivity{
...
private void init(){
//Getting appropriate view model
passwordViewModel = ViewModelProviders.of(this).get(ChangePasswordViewModel.class);
// Starting to observe LiveData
passwordViewModel.getResponseCode().observe(this, responseCode -> {
Log.info("Server response is " + responseCode);
});
//Sending new password to server
buttonPassChange.setOnClickListener(view ->
passwordViewModel.sendChangePasswordRequest("newPass")
);
}
...
}
Problem is that after the first time I send request to server using sendChangePasswordRequest(...) observe code in activity
passwordViewModel.getResponseCode().observe(this, responseCode -> {
Log.info("Server response is " + responseCode);
});
fires every time after I rotate the screen. Why is that happening? Value of MutableLiveData responseCode hasn't been updated since the last server call, so why does .observe() fires if there were no changes to live data?
回答1:
That is an intended behavior, as you can see in documents:
observe (LifecycleOwner owner, Observer observer) Adds the given observer to the observers list within the lifespan of the given owner. The events are dispatched on the main thread. If LiveData already has data set, it will be delivered to the observer.
If you want to observe the change in view state then you should create and observe a view state instead of a network request, google already provided an example for cases like this.
回答2:
In addition to answer above, it's important to understand the scenarios in which using ViewModel & LiveData observers, to observe only once, this article explains them and shows a way to deal with it easily: Working with LiveData and Events
来源:https://stackoverflow.com/questions/49318011/android-live-data-observe-always-fires-after-config-change