3

Dans mon application Android, im suivant les composants de l'architecture avec le modèle mvvm. mon application fait un appel réseau pour afficher l'information météo.appel est fait à partir du référentiel qui renvoie un livedata de réponse au viewmodel, qui est observé par mon activité principale.Observant viewmodel pour la deuxième fois renvoie null dans android

l'application fonctionne très bien, sauf pour une condition, chaque fois que je déconnecter l'Internet pour tester l'échec cas, il se gonfle vue d'erreur selon les besoins

dans la vue d'erreur j'ai un bouton de nouvelle tentative, ce qui rend l'appel de méthode observez à nouveau le viewmodel (cette méthode a également été appelée par oncreate() pour la première fois)

même après la mise en marche d'Internet, et en cliquant sur le bouton Réessayer qui écoute l'observable. Les données deviennent nulles.

Je ne sais pas why.please aider quelqu'un

REFERENTIEL

@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; 
} 
} 

OBSERVER MÉTHODE DE L'ACTIVITÉ

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

BOUTON TENTATIVE DE L'ACTIVITÉ

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

@al_mukhtar Avez-vous trouvé une solution? –

Répondre

2

Mise à jour: - 5 Décembre 2017

J'ai eu la chance de rencontrer Lyla Fujiwara, lors des journées Google Developer, Inde, où je lui ai posé la même question . Elle m'a suggéré d'user Transformations.switchMap(). Voici la solution mise à jour -

@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's value 
    * which in turn calls the `Transformations.switchMap()` function and updates the data and we get 
    * call back 
    */ 
    public void setNetworkInformation() { 
    networkInfoObservable.setValue(null); 
    } 
} 

Code de l'activité sera mise à jour -

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

Cela semble la solution la plus importante et propre à moi pour l'instant, je vais mettre à jour la réponse si je meilleure solution plus tard.

Regardez-la droidCon NYC video pour plus d'informations sur LiveData. Le référentiel officiel de Google pour LiveData est le https://github.com/googlesamples/android-architecture-components/ pour le projet GithubBrowserSample.

Ancien code

Je n'ai pas pu trouver une solution appropriée à cela, mais cela fonctionne jusqu'à présent - Déclare ViewModel en dehors de la observeViewModel() et changer la fonction comme celui-ci -

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

Mise à jour 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; 
} 

} 

Maintenant Réessayez le bouton, appelez à nouveau la fonction observeViewModel et transmettez-lui le mHomeViewModel. Maintenant, vous devriez être en mesure d'obtenir une réponse.

+0

Merci pour la réponse élaborée bro –

+1

@al_mukthar Toujours heureux d'aider et la meilleure façon d'aider est via le code approprié. :) –