I want to know what is the best approach to display some sort of message in the view from the ViewModel. My ViewModel is making a POST call and "onResult" I want to pop up a message to the user containing a certain message.
This is my ViewModel:
public class RegisterViewModel extends ViewModel implements Observable {
.
.
.
public void registerUser(PostUserRegDao postUserRegDao) {
repository.executeRegistration(postUserRegDao).enqueue(new Callback<RegistratedUserDTO>() {
@Override
public void onResponse(Call<RegistratedUserDTO> call, Response<RegistratedUserDTO> response) {
RegistratedUserDTO registratedUserDTO = response.body();
/// here I want to set the message and send it to the Activity
if (registratedUserDTO.getRegisterUserResultDTO().getError() != null) {
}
}
});
}
And my Activity:
public class RegisterActivity extends BaseActivity {
@Override
protected int layoutRes() {
return R.layout.activity_register;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
ActivityRegisterBinding binding = DataBindingUtil.setContentView(this, layoutRes());
binding.setViewModel(mRegisterViewModel);
}
What would the best approach be in this case?
We can use a SingleLiveEvent
class as a solution. But it is a LiveData
that will only send an update once. In my personal experience, using an Event Wrapper class with MutableLiveData
is the best solution.
Here is a simple code sample.
Step 1 :
Create an Event
class (this is a boilerplate code you can reuse for any android project).
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
Step 2 :
At the top of your View Model class, define a MutableLiveData
with wrapper (I used a String here, but you can use your required data type), and a corresponding live data for encapsulation.
private val statusMessage = MutableLiveData<Event<String>>()
val message : LiveData<Event<String>>
get() = statusMessage
Step 3 :
You can update the status message within the functions of the ViewModel
like this:
statusMessage.value = Event("User Updated Successfully")
Step 4 :
Write code to observe the live data from the View
(activity or fragment)
yourViewModel.message.observe(this, Observer {
it.getContentIfNotHandled()?.let {
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
}
})
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