I created the instance of View Model in onCreate
method of an activity.
ticketViewModel = ViewModelProviders.of(this).get(TicketViewModel.class);
Then i have a method, AddTicket
, which uses viewModel
to hit a service and on response from viewModel
i dismiss loading animation.
public void addTicket(View view){
ticketViewModel.AddTicket(id).observe(this, response ->{
dismissLoadingAnimation();
}
Now after adding a ticket, user can repress the Add Ticket
button, and the addTicket()
method will be called again.
but this time observer
defined in ViewModel gets called 2 times, resulting in 2 network calls, and 2 dismissLoadingAnimation
execution.
And if i keep pressing addTicket
button, the number of executing observer defined inside ViewModel
keep increases.
This is my View Model code.
public class TicketViewModel extends AndroidViewModel implements IServiceResponse {
MutableLiveData<String> mObservableResponse = new MutableLiveData<String>();
public MutableLiveData AddTicket(String id){
JsonObject jsonObject= new JsonObject();
jsonObject.addProperty("id", id);
NetworkUtility networkUtility= new NetworkUtility(this, ADD_TICKET);
networkUtility.hitService(URL, jsonObject, RequestMethods.POST);
return mObservableResponse;
}
@Override
public void onServiceResponse(String response, String callType){
if(serviceTag.equalsIgnoreCase(ADD_TICKET)){
mObservableResponse.setValue("success");
}
}
}
I had similar problem. You could try to use SingleLiveEvent
Or, in my, more complicated case, i had to use custom observer. It would looks like this:
And using it like:
If you are willing to do some changes, i think we can handle it in much cleaner way
In ViewModel
In 'onCreate' of your Activity/Fragment
The main concept is to divide the responsibilities, Activity/Fragment doesn't need to know which process is going on, they only need to know what are the current properties/state of there child views.
We need to maintain a LiveData in ViewModels for each changing property/state depending on Views. ViewModel needs to handle the view states depending on whats happening.
Only responsibility the Activity/Fragment has about a process is to trigger it and forget and ViewModel needs handle everything(like informing Repositories to do the work and changing View Properties).
In your Case, 'addTicket' is a process about which Activity/Fragment doesn't need to know about there status. The only responsibility of Activity/Fragment about that process is to trigger it.
ViewModel is one who needs to analyze the state of process(in-progress/success/failed) and give appropriate values to the LiveDatas to inform the respective Views
I can suggest few changes to your code to solve the problem with the above mentioned pointers
ViewModel
View
Hope this is of help :)
The number of executing observer defined inside
ViewModel
keep increases becasue with every click You're registering new observers. You're not supposed to register observer withonClick()
method.You should do it in
onCreate()
method of yourActivity
or inonViewCreated
method of your fragment. If You'll do that, there won't be a need toremoveObserver
when You'll finish work.Lifecycle
mechanism will cover it for you.But if you really want answer for you question, this is how you can do it
Passing
this
means passing yourActivity
, or there is a second way:You only need to call the
observe
once, I prefer to do it inonResume
and then callremoveObserver
inonPause
:You keep adding listeners to the data so you get multiple callbacks.
Edit:
I took an existing code sample of mine for a
Fragment
and renamed everything (I hope), there's no example here for setting the data into theViewModel
but it should beticketViewModel.AddTicket(id);
in your case.