0

I am trying to call the network on button click. I am using singleLiveEvent wrapper because the data need to be sent to the server and retrieve the response only on button click. I am using Volley for GET and POST calls. I am getting response on repository but not on onChanged method. Its getting null from repository.

Viewmodel class

 public void setResponseSingleLiveEvent(String url,Map param){

    responseSingleLiveEvent.setValue(mRepository.changeUserPassword(url,param).getValue());

}

Repository class

  public MutableLiveData<CommonServerResponse> changeUserPassword(String url, Map params) {

    this.postParams = params;

    final MutableLiveData<CommonServerResponse> responseMutableLiveData = new MutableLiveData<>();

    VolleycustomRequest<CommonModel> volleycustomRequest = new VolleycustomRequest<CommonModel>(Request.Method.POST,
            url, CommonModel.class,
            (Response.Listener<CommonModel>)
                    response -> {
                        Log.d(TAG, "changeUserPassword: "+response);

        responseMutableLiveData.setValue(new CommonServerResponse(response));
                    },
            error -> {
        responseMutableLiveData.setValue(new CommonServerResponse(VolleyErrorHelper.getMessage(error)));
            }){

        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            return params;
        }
    };

    AppController.getInstance().addToRequestque(volleycustomRequest);
    return responseMutableLiveData;
}

I want the data to be sent only on button click, not on the start of activity.

Kishan V
  • 41
  • 8
  • You are making a Asynchronous request . You can not return data this way it will return as its initialized . You need to provide a Callback from `onSuccess` . – ADM Jan 08 '19 at 07:32
  • @ADM Is it a good way to use callback in MVVM? Im using Android Architecture components in my app. – Kishan V Jan 08 '19 at 07:46
  • Not sure about `MVVM` but you have to do this what i have stated above. – ADM Jan 08 '19 at 07:54

2 Answers2

0

Your network request is asynchronous, but your setResponseSingleLiveEvent() method isn't waiting for it to complete before checking the returned LiveData's value.

You'll probably want the ViewModel to pass through the LiveData from the Repository, so that the "View" (Activity/Fragment) can subscribe directly to it:

public void onPasswordChanged(String url, Map param) {
    responseLiveData = mRepository.changeUserPassword(url, param);
}

You'll probably want to set some kind of "loading" status in the LiveData object while the network request is in flight. Google has an example of something like that here: https://developer.android.com/jetpack/docs/guide#addendum

If you only want to use a SingleLiveEvent to notify the View when the response completes, you could probably use Transformations.map() to map the result to an event.

Will Ferguson
  • 61
  • 1
  • 5
0

You are setting responseSingleLiveEvent value in ViewModal initial value of LiveData given by repository which is always NULL. You need to Listen to in viewmodel something like this I am doing in my demo app.

  suspend fun getMovieDetail(movieId: String): LiveData<Movie> {
    moviesRepository.getMovieDetail(movieId).observeForever {
        if (it?.status == null) {
            moviesRepository.fetchFullMovieDetails(movieId, addedTime)
        }
    }
   return moviesRepository.getMovieDetail(movieId)
}

Or you can pass context from activity to viewmodel to observe and check if received. You can see full version here

Viewmodel observe livedata

Guru
  • 286
  • 3
  • 6