1
votes

Le motif de bloc n'affiche pas l'utilisateur nouvellement ajouté à sqflite à l'écran

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_example


10 commentaires

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éthode userRepository.insertUser pour vous assurer que la méthode fetchUser 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


3 Réponses :


0
votes

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.


2 commentaires

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



2
votes

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.


1 commentaires

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.



0
votes
...
 if (!snapshot.hasData) {
      userBloc.fetchUser();
        return Center(
          child: CircularProgressIndicator(),
        );
      }
...

0 commentaires