Récemment, j'explore Android Architecture, qui a été introduite récemment par Google. De la Documentation j'ai trouvé ceci:
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<Users>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// do async operation to fetch users
}
}
l'activité peut accéder à cette liste comme suit:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
Ma question est, je vais faire ceci:
dans la fonction loadUsers()
, je récupère les données de manière asynchrone où je vérifie d'abord la base de données (Room) pour ces données
Si je ne reçois pas les données, je vais effectuer un appel API pour récupérer les données sur le serveur Web.
Je vais insérer les données récupérées dans la base de données (Room) et mettre à jour l'interface utilisateur en fonction des données.
Quelle est l'approche recommandée pour faire cela?
Si je lance un Service
pour appeler l'API à partir de la méthode loadUsers()
, comment puis-je mettre à jour la variable MutableLiveData<List<User>> users
à partir de cette Service
?
Je suppose que vous utilisez composants d'architecture Android . En fait, peu importe où vous appelez service, asynctask or handler
pour mettre à jour les données. Vous pouvez insérer les données du service ou de l'asynctask à l'aide de la méthode postValue(..)
. Votre classe ressemblerait à ceci:
private void loadUsers() {
// do async operation to fetch users and use postValue() method
users.postValue(listOfData)
}
Comme la users
est LiveData
, la base de données Room
est chargée de fournir les données des utilisateurs où qu'elles soient insérées.
Note:
Dans une architecture de type MVVM, le référentiel est principalement responsable de la vérification et de l'extraction des données locales et des données distantes.
Veuillez utiliser la méthode postValue (..) de Live data à partir du thread d'arrière-plan.
private void loadUsers() {
// do async operation to fetch users and use postValue() method
users.postValue(listOfData)
}
... dans la fonction loadUsers (), je récupère les données de manière asynchrone ... Si je lance un service pour appeler l'API à partir de la méthode loadUsers (), comment puis-je mettre à jour la variable MutableLiveData> users à partir de ce service?
Si l'application récupère les données utilisateur sur un thread d'arrière-plan, postValue (plutôt que setValue ) sera utile.
Dans la méthode loadData, il existe une référence à l'objet "utilisateurs" de MutableLiveData. La méthode loadData extrait également de nouvelles données utilisateur (par exemple, un référentiel).
Désormais, si l'exécution se fait sur un thread en arrière-plan, MutableLiveData.postValue () est mis à jour en dehors des observateurs de l'objet MutableLiveData.
Peut-être quelque chose comme ça:
private MutableLiveData<List<User>> users;
.
.
.
private void loadUsers() {
// do async operation to fetch users
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(new Runnable() {
@Override
public void run() {
// on background thread, obtain a fresh list of users
List<String> freshUserList = aRepositorySomewhere.getUsers();
// now that you have the fresh user data in freshUserList,
// make it available to outside observers of the "users"
// MutableLiveData object
users.postValue(freshUserList);
}
});
}
Jetez un coup d’œil au guide d’architecture Android qui accompagne les nouveaux modules d’architecture tels que LiveData
et ViewModel
. Ils discutent de cette question en profondeur.
Dans leurs exemples, ils ne le mettent pas dans un service. Regardez comment ils le résolvent en utilisant un module "référentiel" et Retrofit. Les addendums au bas incluent des exemples plus complets, notamment l’état du réseau de communication, les erreurs de rapport, etc.
https://developer.Android.com/topic/libraries/architecture/guide.html
A de très bonnes réponses à votre problème. Faites défiler l'écran jusqu'en bas pour voir comment enregistrer la réponse dans votre base de données et mettre à jour l'interface utilisateur à l'aide de LiveData.
Si vous appelez votre api dans le référentiel alors,
Dans Repository:
public MutableLiveData<LoginResponseModel> checkLogin(LoginRequestModel loginRequestModel) {
final MutableLiveData<LoginResponseModel> data = new MutableLiveData<>();
apiService.checkLogin(loginRequestModel)
.enqueue(new Callback<LoginResponseModel>() {
@Override
public void onResponse(@NonNull Call<LoginResponseModel> call, @Nullable Response<LoginResponseModel> response) {
if (response != null && response.isSuccessful()) {
data.postValue(response.body());
Log.i("Response ", response.body().getMessage());
}
}
@Override
public void onFailure(@NonNull Call<LoginResponseModel> call, Throwable t) {
data.postValue(null);
}
});
return data;
}
Dans ViewModel
public LiveData<LoginResponseModel> getUser() {
loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel);
return loginResponseModelMutableLiveData;
}
Dans Activité/Fragment
loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> {
if (loginResponseModel != null) {
Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show();
}
});
Remarque: En utilisant Java_1.8 lambda ici, vous pouvez utiliser sans elle