Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View Model keeps creating instance of Live Data

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");
        }
    }

}
like image 887
dev90 Avatar asked Dec 15 '18 20:12

dev90


2 Answers

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 with onClick() method.

You should do it in onCreate() method of your Activity or in onViewCreated method of your fragment. If You'll do that, there won't be a need to removeObserver 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

yourViewModel.yourList.removeObservers(this)

Passing this means passing your Activity, or there is a second way:

yourViewModel.yourList.removeObserver(observer)

val observer = object : Observer<YourObject> {
    override fun onChanged(t: YourObject?) {
        //todo
    }
}
like image 140
DawidJ Avatar answered Sep 23 '22 20:09

DawidJ


  • The purpose of Viewmodel is to expose observables (Livedata)
  • The purpose of View(Activity/Fragment) is to get these observables and observe them
  • Whenever there is a change in these observables(Livedata) the change is automatically posted to the active subscribed owners(Activity/Fragment), so you need not remove them in onPause/onStop as it is not mandatory

I can suggest few changes to your code to solve the problem with the above mentioned pointers

ViewModel

public class TicketViewModel extends AndroidViewModel implements IServiceResponse {

    MutableLiveData<String> mObservableResponse = new MutableLiveData<String>();

   public LiveData<String> getResponseLiveData(){
        return mObservableResponse;
        }

    public void AddTicket(String id){

        JsonObject jsonObject= new JsonObject();
        jsonObject.addProperty("id",  id);

        NetworkUtility networkUtility= new NetworkUtility(this, ADD_TICKET);
        networkUtility.hitService(URL, jsonObject, RequestMethods.POST);

    }


     @Override
        public void onServiceResponse(String response, String callType){

        if(serviceTag.equalsIgnoreCase(ADD_TICKET)){    
             mObservableResponse.setValue("success");
        }
    }

}

View

    onCreate(){
    ticketViewModel = ViewModelProviders.of(this).get(TicketViewModel.class);
    observeForResponse();
    }

    private void observeForResponse(){
       ticketViewModel.getResponseLiveData().observe(this, response ->{
                            //do what has to be updated in UI
    }
    }

public void addTicket(View view){
     ticketViewModel.AddTicket(id);
    }

Hope this is of help :)

like image 35
Aron_A Avatar answered Sep 26 '22 20:09

Aron_A