Flutter Riverpod&x27;s StreamProvider仅产生一次StreamValue |颤振和;蜂箱

Flutter Riverpod&x27;s StreamProvider仅产生一次StreamValue |颤振和;蜂箱,flutter,dart,riverpod,flutter-hive,Flutter,Dart,Riverpod,Flutter Hive,我编写了一个StreamProvider,在启动后立即收听,以获取有关可能登录用户的所有信息。如果没有用户,那么结果将为null,侦听器将保持加载状态,因此我决定返回一个空用户的默认值,让我知道加载已经完成。 我必须这样做,因为Hive的watch()方法只有在数据更改时才会触发,而在启动时不会触发。 在那之后,我希望watch()方法完成它的工作,但问题是,下面的场景: 启动时:无用户-触发插入用户->监视方法->获取插入用户数据->删除登录用户->未触发监视方法 启动时:完整用户-删除用户

我编写了一个StreamProvider,在启动后立即收听,以获取有关可能登录用户的所有信息。如果没有用户,那么结果将为null,侦听器将保持加载状态,因此我决定返回一个空用户的默认值,让我知道加载已经完成。 我必须这样做,因为Hive的watch()方法只有在数据更改时才会触发,而在启动时不会触发。 在那之后,我希望watch()方法完成它的工作,但问题是,下面的场景:

  • 启动时:无用户-触发插入用户->监视方法->获取插入用户数据->删除登录用户->未触发监视方法

  • 启动时:完整用户-删除用户->触发监视方法->我得到一个空用户->插入用户->未触发监视方法

  • 过了一段时间,我发现我可以随心所欲地使用所有CRUD操作,蜂巢的盒子做了它应该做的事情,但是watch()方法在被触发一次后就不再被触发了

    流提供商:

    final localUsersBoxFutureProvider=FutureProvider((ref)异步{
    final usersBox=wait Hive.openBox(“用户”);
    返回usersBox;
    });
    最终localUserStreamProvider=StreamProvider((ref)异步*{
    final usersBox=wait ref.watch(localUsersBoxFutureProvider.future);
    yield*Stream.value(usersBox.get(0,defaultValue:User());
    yield*usersBox.watch(键:0).map((usersBoxEvent){
    返回usersBoxEvent.value==null?User():usersBoxEvent.value作为用户;
    });
    });
    
    听众:

    return localUserStream.when(
      data: (data) {
        if (data.name == null) {
          print('Emitted data is an empty user');
        } else {
          print('Emitted data is a full user');
        }
    
        return Container(color: Colors.blue, child: Center(child: Row(children: [
          RawMaterialButton(
            onPressed: () async {
              final globalResponse = await globalDatabaseService.signup({
                'email' : 'name@email.com',
                'password' : 'password',
                'name' : 'My Name'
              });
    
              Map<String, dynamic> jsonString = jsonDecode(globalResponse.bodyString);
              await localDatabaseService.insertUser(User.fromJSON(jsonString));
            },
            child: Text('Insert'),
          ),
          RawMaterialButton(
            onPressed: () async {
              await localDatabaseService.removeUser();
            },
            child: Text('Delete'),
          )
        ])));
      },
      loading: () {
        return Container(color: Colors.yellow);
      },
      error: (e, s) {
        return Container(color: Colors.red);
      }
    );
    
    返回localUserStream.when(
    数据:(数据){
    if(data.name==null){
    打印(“发出的数据为空用户”);
    }否则{
    打印(“发出的数据是完全用户”);
    }
    返回容器(颜色:Colors.blue,子项:中心(子项:行(子项:[
    原材料按钮(
    onPressed:()异步{
    final globalResponse=等待globalDatabaseService.signup({
    “电子邮件”:name@email.com',
    “密码”:“密码”,
    “名字”:“我的名字”
    });
    Map jsonString=jsonDecode(globalResponse.bodyString);
    等待localDatabaseService.insertUser(User.fromJSON(jsonString));
    },
    子项:文本('Insert'),
    ),
    原材料按钮(
    onPressed:()异步{
    等待localDatabaseService.removeUser();
    },
    子项:文本('Delete'),
    )
    ])));
    },
    加载:(){
    返回容器(颜色:颜色.黄色);
    },
    错误:(e,s){
    返回容器(颜色:Colors.red);
    }
    );
    
    积垢法:

    Future<void> insertUser(User user) async {
        Box usersBox = await Hive.openBox('users');
        await usersBox.put(0, user);
        await usersBox.close();
      }
    
      Future<User> readUser() async {
        Box usersBox = await Hive.openBox('users');
        User user = usersBox.get(0) as User;
        await usersBox.close();
        return user;
      }
    
      Future<void> removeUser() async {
        Box usersBox = await Hive.openBox('users');
        await usersBox.delete(0);
        await usersBox.close();
      }
    
    Future insertUser(用户)异步{
    Box usersBox=wait-Hive.openBox(“用户”);
    等待usersBox.put(0,用户);
    等待usersBox.close();
    }
    Future readUser()异步{
    Box usersBox=wait-Hive.openBox(“用户”);
    User User=usersBox.get(0)作为用户;
    等待usersBox.close();
    返回用户;
    }
    Future removeUser()异步{
    Box usersBox=wait-Hive.openBox(“用户”);
    等待usersBox.delete(0);
    等待usersBox.close();
    }
    
    你知道我如何告诉StreamProvider watch()方法应该保持活动状态,即使已经发出了一个值

    但是watch()方法在被触发后不再被触发 一次

    这是因为在每次CRUD之后,您都要关闭该框,因此流(使用该框)停止发射值。无论您是从riverpod之外的某个地方调用它(
    await Hive.openBox('users')
    ),它都会调用相同的引用。只有在停止使用时才应该关闭该框,我建议使用autodispose with riverpod在不再使用时关闭它,并可能将这些CRUD方法放在riverpod控制的类中,这样您就可以完全控制该框的生命周期

    final localUsersBoxFutureProvider = FutureProvider.autoDispose<Box>((ref) async {
      final usersBox = await Hive.openBox('users');
    
      ref.onDispose(() async => await usersBox?.close()); //this will close the box automatically when the provider is no longer used
      return usersBox;
    });
    
    final localUserStreamProvider = StreamProvider<User>.autoDispose((ref) async* {
      final usersBox = await ref.watch(localUsersBoxFutureProvider.future);
    
      yield* Stream.value(usersBox.get(0, defaultValue: User()));
      yield* usersBox.watch(key: 0).map((usersBoxEvent) {
        return usersBoxEvent.value == null ? User() : usersBoxEvent.value as User;
      });
    });
    
    final localUsersBoxFutureProvider=FutureProvider.autoDispose((ref)异步{
    final usersBox=wait Hive.openBox(“用户”);
    ref.onDispose(()async=>await usersBox?.close());//当不再使用提供程序时,将自动关闭该框
    返回usersBox;
    });
    最终localUserStreamProvider=StreamProvider.autoDispose((ref)async*{
    final usersBox=wait ref.watch(localUsersBoxFutureProvider.future);
    yield*Stream.value(usersBox.get(0,defaultValue:User());
    yield*usersBox.watch(键:0).map((usersBoxEvent){
    返回usersBoxEvent.value==null?User():usersBoxEvent.value作为用户;
    });
    });
    

    在您的方法中,请使用localUsersBoxFutureProvider中的同一个实例框,并且不要在每个实例框之后关闭该框,当您停止收听
    localUsersBoxFutureProvider时,它将自动关闭

    我将在祈祷中包含您的名字!
    final localUsersBoxFutureProvider = FutureProvider.autoDispose<Box>((ref) async {
      final usersBox = await Hive.openBox('users');
    
      ref.onDispose(() async => await usersBox?.close()); //this will close the box automatically when the provider is no longer used
      return usersBox;
    });
    
    final localUserStreamProvider = StreamProvider<User>.autoDispose((ref) async* {
      final usersBox = await ref.watch(localUsersBoxFutureProvider.future);
    
      yield* Stream.value(usersBox.get(0, defaultValue: User()));
      yield* usersBox.watch(key: 0).map((usersBoxEvent) {
        return usersBoxEvent.value == null ? User() : usersBoxEvent.value as User;
      });
    });