Observing viewmodel a second time returns null in android

In my Android application, im the following architecture components with the mvvm template. my app makes a network call to display weather information. A call is made from a repository that returns a live response group to the viewmodel, which is related to my main activity.

the application works fine, except for one condition, whenever I turn off the Internet to test the case of a crash, it inflates viewing errors as needed

in the error view, I have a redo button that makes the method call again observe the view model (this method was also called oncreate () for the first time that worked)

even after turning on the Internet and pressing the snooze button, which listens to the observed. If the data becomes empty.

I do not know why. Please, help

WAREHOUSE

@Singleton public class ContentRepository { @Inject AppUtils mAppUtils; private RESTService mApiService; @Inject public ContentRepository(RESTService mApiService) { this.mApiService = mApiService; } public MutableLiveData<ApiResponse<WeatherModel>> getWeatherListData() { final MutableLiveData<ApiResponse<WeatherModel>> weatherListData = new MutableLiveData<>(); mApiService.getWeatherList().enqueue(new Callback<WeatherModel>() { @Override public void onResponse(Call<WeatherModel> call, Response<WeatherModel> response) { weatherListData.setValue(new ApiResponse<>(response.body())); } @Override public void onFailure(Call<WeatherModel> call, Throwable t) { weatherListData.setValue(new ApiResponse<>(t)); } }); return weatherListData; } } 

ViewModel

 public class HomeViewModel extends AndroidViewModel { private final LiveData<ApiResponse<WeatherModel>> weatherListObservable; @Inject public HomeViewModel(Application application, ContentRepository contentRepository) { super(application); this.weatherListObservable = contentRepository.getWeatherListData(); } public LiveData<ApiResponse<WeatherModel>> getWeatherListObservable() { return weatherListObservable; } } 

OBSERVING METHOD IN ACTIVITIES

 private void observeViewModel() { mHomeViewModel = ViewModelProviders.of(this, mViewModelFactory).get(HomeViewModel.class); mHomeViewModel.getWeatherListObservable().observe(this, weatherModelApiResponse -> { if (weatherModelApiResponse.isSuccessful()) { mErrorView.setVisibility(View.GONE); mBinding.ivLoading.setVisibility(View.GONE); try { setDataToViews(weatherModelApiResponse.getData()); } catch (ParseException e) { e.printStackTrace(); } } else if (!weatherModelApiResponse.isSuccessful()) { mBinding.ivLoading.setVisibility(View.GONE); mDialogUtils.showToast(this, weatherModelApiResponse.getError().getMessage()); mErrorView.setVisibility(View.VISIBLE); } }); } 

RETRY BUTTON IN ACTIVITY

 @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_retry: mErrorView.setVisibility(View.GONE); observeViewModel(); break; } } 
+3
source share
1 answer

Updated: - December 5, 2017

I was fortunate enough to meet Lila Fujiwara during the Google Developer Days in India, where I asked her the same question. She invited me to the user Transformations.switchMap() . Below is an updated solution -

 @Singleton public class SplashScreenViewModel extends AndroidViewModel { private final APIClient apiClient; // This is the observable which listens for the changes // Using 'Void' since the get method doesn't need any parameters. If you need to pass any String, or class // you can add that here private MutableLiveData<Void> networkInfoObservable; // This LiveData contains the information required to populate the UI private LiveData<Resource<NetworkInformation>> networkInformationLiveData; @Inject SplashScreenViewModel(@NonNull APIClient apiClient, @NonNull Application application) { super(application); this.apiClient = apiClient; // Initializing the observable with empty data networkInfoObservable = new MutableLiveData<Void>(); // Using the Transformation switchMap to listen when the data changes happen, whenever data // changes happen, we update the LiveData object which we are observing in the MainActivity. networkInformationLiveData = Transformations.switchMap(networkInfoObservable, input -> apiClient.getNetworkInformation()); } /** * Function to get LiveData Observable for NetworkInformation class * @return LiveData<Resource<NetworkInformation>> */ public LiveData<Resource<NetworkInformation>> getNetworkInfoObservable() { return networkInformationLiveData; } /** * Whenever we want to reload the networkInformationLiveData, we update the mutable LiveData value * which in turn calls the `Transformations.switchMap()` function and updates the data and we get * call back */ public void setNetworkInformation() { networkInfoObservable.setValue(null); } } 

The action code will be updated as -

 final SplashScreenViewModel splashScreenViewModel = ViewModelProviders.of(this, viewModelFactory).get(SplashScreenViewModel.class); observeViewModel(splashScreenViewModel); // This function will ensure that Transformation.switchMap() function is called splashScreenViewModel.setNetworkInformation(); 

This seems to be the most visible and correct solution for me now, I will update the answer if I get a better solution later.

See her droidCon NYC video for more information on LiveData. The official Google repository for LiveData https://github.com/googlesamples/android-architecture-components/ search for the GithubBrowserSample project.

Old code

I could not find a suitable solution for this, but it still works - Declare the ViewModel outside of observeViewModel() and change this function as follows:

 private void observeViewModel(final HomeViewModel homeViewModel) { homeViewModel.getWeatherListObservable().observe(this, weatherModelApiResponse -> { if (weatherModelApiResponse.isSuccessful()) { mErrorView.setVisibility(View.GONE); mBinding.ivLoading.setVisibility(View.GONE); try { setDataToViews(weatherModelApiResponse.getData()); } catch (ParseException e) { e.printStackTrace(); } } else if (!weatherModelApiResponse.isSuccessful()) { mBinding.ivLoading.setVisibility(View.GONE); mDialogUtils.showToast(this, weatherModelApiResponse.getError().getMessage()); mErrorView.setVisibility(View.VISIBLE); } }); } 

Update HomeViewModel -

 public class HomeViewModel extends AndroidViewModel { private final LiveData<ApiResponse<WeatherModel>> weatherListObservable; @Inject public HomeViewModel(Application application, ContentRepository contentRepository) { super(application); getWeattherListData(); } public void getWeatherListData() { this.weatherListObservable = contentRepository.getWeatherListData(); } public LiveData<ApiResponse<WeatherModel>> getWeatherListObservable() { return weatherListObservable; } } 

Now the observeViewModel button , call the observeViewModel function observeViewModel and pass mHomeViewModel . Now you can get an answer.

+2
source

Source: https://habr.com/ru/post/1273703/


All Articles