Je suis actuellement en train de refactoriser le code existant pour utiliser les composants d'architecture Android et de configurer une demande de db et de vol dans un type de structure de référentiel. Ainsi, la couche de présentation/domaine demande au référentiel de faire en sorte que LiveData-Objects l'observe ou lui demande de se synchroniser avec le serveur, après quoi les anciennes entrées db sont supprimées et toutes les actuelles sont récupérées du serveur.La liste LiveData ne se met pas à jour lors de la mise à jour de la base de données
J'ai écrit des tests pour la partie de synchronisation, donc je suis sûr que les objets sont récupérés et insérés dans la base de données correctement. Mais lors de l'écriture d'un test pour observer les entrées de cette table db (et tester si les objets ont été sauvegardés correctement avec tout ce qu'il faut faire avant de les mettre en db) le LiveData> J'observe, ne se déclenche pas. Dans l'extrait suivant, vous pouvez supposer que la méthode synchronizeFormsWithServer (...) fonctionne correctement et effectue des opérations de base de données de manière asynchrone. Il contient des opérations qui suppriment tous les objets-formes de la base de données qui ne sont pas présents dans la liste des formulaires extraits du serveur et insèrent tous les nouveaux. Depuis au début de l'essai, la base de données est vide cela ne devrait pas beaucoup d'importance que
Le test dans lequel l'observateur ne soit pas déclenché:
@Test
public void shouldSaveFormsFromServerIntoDb() throws Exception
{
Lifecycle lifecycle = Mockito.mock(Lifecycle.class);
when(lifecycle.getCurrentState()).thenReturn(Lifecycle.State.RESUMED);
LifecycleOwner owner = Mockito.mock(LifecycleOwner.class);
when(owner.getLifecycle()).thenReturn(lifecycle);
final CountDownLatch l = new CountDownLatch(19);
formRepository.allForms().observe(owner, formList ->
{
if (formList != null && formList.isEmpty())
{
for (Form form : formList)
{
testForm(form);
l.countDown();
}
}
});
formRepository.synchronizeFormsWithServer(owner);
l.await(2, TimeUnit.MINUTES);
assertEquals(0, l.getCount());
}
Le code FormRepository:
@Override
public LiveData<List<Form>> allForms()
{
return formDatastore.getAllForms();
}
Le datastore:
@Override
public LiveData<List<Form>> getAllForms()
{
return database.formDao().getAllForms();
}
Le code formDao (base de données est mis en œuvre comment vous ex Pect à partir de la chambre):
@Query("SELECT * FROM form")
LiveData<List<Form>> getAllForms();
Il peut très bien être, que je ne comprenais pas quelque chose sur le LiveData-composants, parce que c'est la première fois les utiliser, alors peut-être que je suis quelque chose de fondamentalement mauvais.
Chaque peu d'aide est très appréciée :)
PS: Je suis tombé sur THIS après, qui traite d'un problème similaire, mais depuis que je suis actuellement pas en utilisant DI du tout et il suffit d'utiliser une seule instance de le formrepository (qui n'a qu'une seule instance de formDao associée) Je ne pense pas que ce soit le même problème.
J'hésite à utiliser votre approche car cela signifierait d'encapsuler tous les appels à mon dépôt dans une asynctask ou quelque chose de similaire, lorsque Room autorise explicitement de telles opérations sur le thread principal si LiveData est renvoyé. Après avoir lu tous les commentaires/messages de chat dans votre question je trouve cela très étrange, cette pièce se comporte comme vous le pensez, même si cela semble être le cas S'il n'y a pas vraiment d'autre option, j'accepterai votre réponse fais comme ça. Mais peut-être que quelqu'un peut jeter plus de lumière sur le problème et trouver un moyen de rendre LiveData directement à partir du dao :) –
J'aimerais aussi cela parce qu'il est un peu étrange que cela se comporte de cette façon :) – joao86
mettre à jour l'interface utilisateur lorsqu'un autre service a modifié les valeurs de la base de données? Parce que oui, si vous actualisez uniquement les valeurs lorsque vous appelez la méthode get (...) du référentiel qui ne pose aucun problème, mais si par exemple un ContentProvider insère quelque chose dans la base de données, je ne pense pas que l'interface affichera change jusqu'à ce que le prochain temps soit appelé (...). Parler de votre code de question lié ici –