通过域层连接块:如何从多个块监听一个流?

问题描述 投票:0回答:1

我在存储库中有一个方法,它在调用时从 api 获取一些数据。该方法可以从两个、三个或更多块调用。因此,为了优化 api 调用,该方法应该只被调用一次,并且这三个块应该得到结果。

根据 bloc 文档和here提供的示例,我已将存储库方法更改为如下所示的流:

 Stream<UserInfo> getUserInfo(
  {required String userKey, required String caller}) async* {
print("Repo Caller is $caller");

  UserInforesponse =
      await provider.getUserInfo(
    patientKey: patientKey,
  );

  yield response;
  }

在需要此方法结果的块中,我这样做:

await emit.forEach(
      repo.getUserInfo(userKey: userKey,caller:"bloc1"),
      onData: (UserInfo response) {
        print("bloc1 got data");
        return state.copyWith( ...  );
      },
    );

在块 2 ,3 ... 中使用相同的方法:

await emit.forEach(
      repo.getUserInfo(userKey: userKey,caller:"bloc2"),
      onData: (UserInfo response) {
        print("bloc2 got data");
        return state.copyWith(  ...  );
         
      },
    );

但问题是这些区块没有监听一个流。他们正在创建自己的个人流。因此,结果会打印在输出中:

 Repo Caller is bloc1
 Repo Caller is bloc2

所以 api 服务被调用两次,如果我需要这个 api 结果在 5 个块中,它将被调用 5 次而不是一次。 由于文档中的示例未涵盖这种情况,我怎样才能实现预期的行为。

flutter bloc
1个回答
0
投票

来自

forEach
中的
emmiter
方法的文档:

  /// Subscribes to the provided [stream] and invokes the [onData] callback
  /// when the [stream] emits new data and the result of [onData] is emitted.
  /// .....
  Future<void> forEach<T>(...

下一个问题是:如何创建存储库实例以及如何将其提供/注入到块中 - 它是同一个实例吗? 作为一种选择,在您的集团中,您可以做一些常见的事情,如下所示:

class Bloc1 extends Bloc<SomeEvent, SomeState> {
  final YourRepository _yourRepository
  final StreamSubscription _subscription;

      Bloc1(YourRepository yourRepository) : 
        _yourRepository = yourRepository,
        super(UserState.initial()) {
        ...
        _subscription = _yourRepository.userInfoStream.listen((userInfo){
            emit(state.copyWith(...));
          }, onError: (error) {
            emit(state.copyWith(...));
          });
        ...
      }

      void getUserInfo(
             required String userKey, 
             required String caller,
      ){
         _yourRepository.getUserInfo(userKey, caller);
      }
    
      @override
      Future<void> close() {
        _subscription?.cancel();
        return super.close();
      }
    }
...

在你的仓库中是这样的:

    class YourRepository{
      final _userInfoController = StreamController<List<int>>.broadcast();
      Stream<UserInfo> get userInfoStream => _userInfoController.stream;
    
     void getUserInfo({
            required String userKey, 
            required String caller,
     }) async* {
    
         final userInforesponse = await provider.getUserInfo(
           patientKey: patientKey,
         );
    
         _userInfoController.add(userInforesponse);
     }
    
     void dispose() {
       _userInfoController.close();
     }
   }
© www.soinside.com 2019 - 2024. All rights reserved.