J'utilise la base de données sqflite
pour enregistrer la liste des utilisateurs.
J'ai un écran de liste d'utilisateurs, qui montre la liste des utilisateurs et il a un bouton fab,
en cliquant sur le bouton fab, l'utilisateur est redirigé vers l'écran suivant où il peut ajouter un nouvel utilisateur à la base de données.
Le nouvel utilisateur est correctement inséré dans la base de données
mais lorsque l'utilisateur appuie sur le bouton de retour et revient à l'écran de la liste des utilisateurs,
l'utilisateur nouvellement ajouté n'est pas visible à l'écran.
Je dois fermer l'application et la rouvrir, puis le nouvel utilisateur ajouté est visible à l'écran.
J'utilise le modèle bloc
et voici mon code pour afficher la liste des utilisateurs
XXX
Voici mon code de bloc
class UserBloc implements BlocBase { final _users = BehaviorSubject<List<User>>(); Observable<List<User>> get users => _users.stream; fetchUser() async { await userRepository.initializeDatabase(); final users = await userRepository.getUserList(); _users.sink.add(users); } insertUser(String name,int id,int phoneNumber) async { userRepository.insertUser(User(id, name, phoneNumber)); fetchUser(); } updateUser(User user) async { userRepository.updateUser(user); } deleteParticularUser(User user) async { userRepository.deleteParticularUser(user); } deleteAllUser() { return userRepository.deleteAllUsers(); } @override void dispose() { _users.close(); } }
Comme Remi a publié une réponse disant que je devrais essayer BehaviorSubject
et ReplaySubject
que j'ai essayé mais cela n'aide pas. J'ai également appelé fetchUser ();
à l'intérieur de insertUser ()
comme indiqué dans les commentaires
Voici le lien de l'exemple complet
https://github.com/pritsawa/sqflite_example3 Réponses :
Le problème est que vous utilisez un PublishSubject
.
Lorsqu'un nouvel auditeur s'abonne à un PublishSubject
, il ne reçoit pas la valeur précédemment envoyée et ne recevra que les événements suivants.
La solution la plus simple consiste à utiliser un BehaviorSubject
ou un ReplaySubject
à la place. Ces deux personnes appelleront directement leur auditeur avec les dernières valeurs.
Ne marche pas. J'ai essayé de remplacer PublishSubject par BehaviorSubject et ReplaySubject.
Jetez un œil à ma question mise à jour. J'ai essayé votre chemin mais ça n'aide pas
Suite aux commentaires, il semble que vous n'ayez pas une seule instance de votre UsersBloc dans ces deux pages. HomePage et UserDetails renvoient un BlocProvider qui instancie une instance UsersBloc. Parce que vous avez deux instances de blocs (que vous ne devriez pas avoir), vous ne mettez pas à jour correctement les flux.
La solution est de supprimer le BlocProvider de ces deux pages (HomePage et UserDetail) et d'y insérer le widget MaterialApp pour rendre la même instance disponible sur les deux pages.
class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return UserList(), ); } }
La page d'accueil sera:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( bloc: UserBloc(), child:MaterialApp(...
Supprimez le BlocProvider de UserDetail comme bien. Dans UsersBloc, appelez ensuite fetchUser () à l'intérieur de la méthode insertUser () après l'insertion de l'utilisateur, pour actualiser la base de données et mettre à jour le flux des utilisateurs.
Aussi, comme l'a dit Rémi Rousselet, utilisez l'un des sujets qui renvoie les valeurs précédentes.
cela fonctionne même avec PublishSubject. Merci beaucoup pour votre temps. Étant un débutant en bloc, je ne savais pas que nous ne devrions avoir qu'une seule instance de bloc pour toutes les pages s'il s'agit du même bloc.
... if (!snapshot.hasData) { userBloc.fetchUser(); return Center( child: CircularProgressIndicator(), ); } ...
Pouvez-vous montrer votre bloc?
@ RémiRousselet J'ai ajouté le code dans la question, veuillez jeter un œil
Tout d'abord, comme Remi l'a dit, vous devez utiliser un BehaviorSubject. Le principal problème que vous rencontrez est qu'après avoir inséré le nouvel utilisateur, vous ne mettez pas à jour le flux des utilisateurs à partir de la base de données. Ainsi, dans la méthode insertUser (), en plus de l'appel userRepository.insertUser (), vous devez également appeler fetchUser () pour demander à la base de données la nouvelle liste d'utilisateurs stockés et mettre à jour votre flux d'utilisateurs avec de nouvelles données.
@Luksprog J'ai essayé à la fois BehaviourSubject et ReplaySubject et ajouté fetchUser () dans insertUser (), mais cela ne fonctionne toujours pas. Quel est le point d'appeler l'utilisateur à récupérer dans insertUser alors que j'insère en complétant un écran différent, j'ai essayé votre chemin mais cela ne fonctionne pas
Je suis d'accord avec @Luksprog, cela devrait aider
@KirillShashov a essayé mais ne fonctionne pas. Veuillez jeter un œil à ma question mise à jour. J'ai essayé la réponse de Remi et Luksprog
Quel est l'intérêt d'appeler fetch user dans insertUser ... - le fait est qu'après avoir inséré un nouvel utilisateur, il faut également interroger la base de données pour obtenir la nouvelle liste d'utilisateurs. Sans requerying la base de données, le flux des utilisateurs ne peut pas vraiment savoir que la base de données a été mise à jour (à moins que vous ayez une sorte de rappel sur la base de données?!). Êtes-vous sûr d'utiliser la même instance UserBloc dans la liste des utilisateurs et les pages de détails?
@GoFudgeYourSelves Avez-vous essayé d'ajouter
wait
pour l'appel de méthodeuserRepository.insertUser
pour vous assurer que la méthodefetchUser
est exécutée après l'insertion?@KirillShashov a essayé d'ajouter await mais n'aide pas. J'ai ajouté mon lien de dépôt de github, si vous avez le temps, jetez un œil
@Luksprog ouais je n'ai qu'un seul bloc dans mon projet. J'ai mis à jour la question pour mettre à jour le lien github, si vous avez le temps, veuillez jeter un œil