4
votes

i have a simple app that polls a service to display country list in a recyclerview. Here i am using LiveData to update the recyclerview whenever there is any change in the country list. Trouble is, LiveData's onChanged method is invoked only the first time setValue is called. But after that if there are any further changes to the data the onChanged is not invoked??

Following is my code for more info -

CountryListFragment

        //Setup observer
    Observer<List<CountryModel>> myObserver = new Observer<List<CountryModel>>() {
        @Override
        public void onChanged(@Nullable List<CountryModel> countryModels) {
            mCountryList = countryModels;
            //Update recyclerview
            myAdapter.updateRecyclerView(mCountryList);
        }
    };
    //Set Observer for Viewmodel
    countryViewModel.getmCountryList().observe(this,myObserver);

CountryViewModel

public class CountryViewModel extends AndroidViewModel { private MutableLiveData> mCountryList; private MyRetrofitClient myRetrofitClient;

public CountryViewModel(@NonNull Application application) {
    super(application);
}

public void init(){
    mCountryList = new MutableLiveData<>();
    myRetrofitClient = new MyRetrofitClient();
    **mCountryList = myRetrofitClient.getCountryList();   //This works**
    pollCountryList();
}

//Create polling request for every 10 secs
private void pollCountryList(){
    final Handler mHandler = new Handler();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0; i<30;i++){
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //Call API on main thread
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            **myRetrofitClient.getCountryList();  //NOT CALLING ONCHANGED??**
                        }
                    });
                }

            }
        }).start();
}

public MutableLiveData<List<CountryModel>> getmCountryList() {
    return mCountryList;
}

MyRetrofitClient.getCountryList()

public MutableLiveData<List<CountryModel>> getCountryList(){
    final MutableLiveData<List<CountryModel>> lstResult = new MutableLiveData<>();
    MockServiceInterface serviceInterface = mRetrofit.create(MockServiceInterface.class);
    Call<List<CountryModel>> countryList = serviceInterface.getCountryList();
    countryList.enqueue(new Callback<List<CountryModel>>() {
        @Override
        public void onResponse(Call<List<CountryModel>> call, Response<List<CountryModel>> response) {
            if (response.isSuccessful()){
                List<CountryModel> lstResponse = response.body();
                lstResult.setValue(lstResponse);
            }else {
                System.out.print(response.errorBody());
            }
        }
        @Override
        public void onFailure(Call<List<CountryModel>> call, Throwable t) {
            t.printStackTrace();
        }
    });
    return lstResult;
}

Thanks!

EDIT:

Some additional observations- When i call setValue method of MutableLiveData instance (mCountryList) inside my CountryViewModel it invokes the onChanged method each time.

However its different in case of MyRetrofitClient. The first time setValue is called in MyRetrofitClient.getCountryList(), it invokes the onChanged method. But later it does not.

1

1 Answers

0
votes

Sorry, I misunderstood question at first.

You are not receiving changes because you never called setValue on mCountryList.

Method getCountryList() is returning new object MutableLiveData<List<CountryModel>> lstResult everything it is called, to which no one is observing.

Solution:

Instead of returning MutableLiveData object with getCountryList, set mCountryList in onResponse().

Code

public void init(){
    mCountryList = new MutableLiveData<>();
    myRetrofitClient = new MyRetrofitClient();
    myRetrofitClient.getCountryList();
    pollCountryList();
}

public LiveData<List<CountryModel>> getCountryListener() {
    return mCountryList;
}

public void getCountryList(){
    MockServiceInterface serviceInterface = mRetrofit.create(MockServiceInterface.class);
    Call<List<CountryModel>> countryList = serviceInterface.getCountryList();
    countryList.enqueue(new Callback<List<CountryModel>>() {
        @Override
        public void onResponse(Call<List<CountryModel>> call, Response<List<CountryModel>> response) {
            if (response.isSuccessful()){
                List<CountryModel> lstResponse = response.body();
                mCountryList.setValue(lstResponse);
            }else {
                System.out.print(response.errorBody());
            }
        }
        @Override
        public void onFailure(Call<List<CountryModel>> call, Throwable t) {
            t.printStackTrace();
        }
    });
}

Use getCountryListener() to observe.

Activity:

countryViewModel.getCountryListener().observe(this,myObserver);