Rxdart combinelaststream 功能不起作用

Posted

技术标签:

【中文标题】Rxdart combinelaststream 功能不起作用【英文标题】:Rxdart combinelaststream function does not work 【发布时间】:2020-05-27 20:40:59 【问题描述】:

我将合并两个流。但它不起作用。我的错误是什么?

我的构建函数是 ;

  @override
  Widget build(BuildContext context) 
    return StreamBuilder(
      stream: Observable.combineLatest2(
        getAllDBAccountsBloc.getAllDBAccountsStream,
        deleteDBAccountBloc.deleteDBAccountStream,
        (accountList, deleteAccountResultModel) 
          print("my account list : $accountList == null");
          return AccountsCombinerResult(
            deleteAccountResultBlocModel: deleteAccountResultModel,
            accountsList: accountList,
          );
        ,
      ),
      builder: (context, snapshot) 
        print("hasData : $snapshot.hasData");
        if (snapshot.hasData) accountsCombinerResult = snapshot.data;
        if (snapshot.hasError) return Text(snapshot.error.toString());
        return _buildWidget;
      ,
    );
  

Get All DB Accounts Stream Bloc 是

class GetAllDBAccountsBloc 
  final _getAllDBAccountsFetcher = PublishSubject<List<AccountDatabaseModel>>();

  Observable<List<AccountDatabaseModel>> get getAllDBAccountsStream => _getAllDBAccountsFetcher.stream;

  getAllDBAccounts() async 
    print("accounts getting");
    _getAllDBAccountsFetcher.sink.add(null);
    await new Future.delayed(const Duration(seconds: 1));
    _getAllDBAccountsFetcher.sink.add(await Repository.getAllDBAccounts());
    print("accounts get");
  

  dispose() 
    _getAllDBAccountsFetcher.close();
  


final getAllDBAccountsBloc = GetAllDBAccountsBloc();

删除数据库帐户群

class DeleteDBAccountBloc 
  final _deleteDBAccountFetcher = PublishSubject<DeleteAccountResultBlocModel>();

  Observable<DeleteAccountResultBlocModel> get deleteDBAccountStream => _deleteDBAccountFetcher.stream;

  deleteDBAccount(DeleteAccountRequestBlocModel requestModel) async 
    _deleteDBAccountFetcher.sink.add(DeleteAccountResultBlocModel());
    await new Future.delayed(const Duration(seconds: 1));
    _deleteDBAccountFetcher.sink.add(await Repository.deleteDBAccount(requestModel));
  

  dispose() 
    _deleteDBAccountFetcher.close();
  


final deleteDBAccountBloc = DeleteDBAccountBloc();

Combiner 结果类是

class AccountsCombinerResult 
  final DeleteAccountResultBlocModel deleteAccountResultBlocModel;
  final List<AccountDatabaseModel> accountsList;

  AccountsCombinerResult(
    @required this.accountsList,
    @required this.deleteAccountResultBlocModel,
  );

它的我在 android studio 上运行日志..

I/flutter (28323):帐户获取

I/flutter (28323): hasData : false

I/flutter (28323): hasData : false

I/flutter (28323):帐户获取

流工作,但我没有得到 AccountsCombiner 结果数据。

此构建方法有效,但我不想使用它...

  @override
  Widget build(BuildContext context) 
    return StreamBuilder(
      stream: getAllDBAccountsBloc.getAllDBAccountsStream,
      builder: (context, getDbAccountsSnapshot) 
        return StreamBuilder(
          stream: deleteDBAccountBloc.deleteDBAccountStream,
          builder: (context, deleteDbAccountStreamSnapshot) 
            if (deleteDbAccountStreamSnapshot.hasData && getDbAccountsSnapshot.hasData) 
              print("qweqweq");
              accountsCombinerResult = AccountsCombinerResult(
                accountsList: getDbAccountsSnapshot.data,
                deleteAccountResultBlocModel: deleteDbAccountStreamSnapshot.data,
              );
            
            if (getDbAccountsSnapshot.hasError) return Text(getDbAccountsSnapshot.error.toString());
            if (deleteDbAccountStreamSnapshot.hasError) return Text(deleteDbAccountStreamSnapshot.error.toString());
            return _buildWidget;
          ,
        );
      ,
    );
  

【问题讨论】:

【参考方案1】:

每次调用build 方法时,您都在构建一个新流。您需要将流引用保持在状态。


StreamController<AccountsCombinerResult> _streamController = StreamController<AccountsCombinerResult>();

@override
void initState() 
    super.initState();
    _streamController.addStream(Observable.combineLatest2(
        getAllDBAccountsBloc.getAllDBAccountsStream,
        deleteDBAccountBloc.deleteDBAccountStream,
        (accountList, deleteAccountResultModel) 
          print("my account list : $accountList == null");
          return AccountsCombinerResult(
            deleteAccountResultBlocModel: deleteAccountResultModel,
            accountsList: accountList,
          );
        ,
      ));


@override
void dispose() 
    super.dispose();
    _streamController.close();


@override
Widget build(BuildContext context) 
    return StreamBuilder(
      stream: _streamController.stream,
      builder: (context, snapshot) 
        print("hasData : $snapshot.hasData");
        if (snapshot.hasData) accountsCombinerResult = snapshot.data;
        if (snapshot.hasError) return Text(snapshot.error.toString());
        return _buildWidget;
      ,
    );

为了使这更容易,您可以使用提供程序包中的StreamProvider。 https://pub.dev/packages/provider https://pub.dev/documentation/provider/latest/provider/StreamProvider-class.html

它只构建一次流。

@override
Widget build(BuildContext context) 
    return StreamProvider<AccountsCombinerResult>(
      initialData: null, // not sure if this works, you can try []
      create: () => Observable.combineLatest2(
        getAllDBAccountsBloc.getAllDBAccountsStream,
        deleteDBAccountBloc.deleteDBAccountStream,
        (accountList, deleteAccountResultModel) 
          print("my account list : $accountList == null");
          return AccountsCombinerResult(
            deleteAccountResultBlocModel: deleteAccountResultModel,
            accountsList: accountList,
          );
        ,
      ),
      catchError: (context, error) => AccountsCombinerResult(
          deleteAccountResultBlocModel: null,
          accountsList: null,
          error: error,
      ), 
      child: Builder(
        builder: (context) 
            final data = Provider.of<AccountsCombinerResult>(context);
            // maybe null check
            if (data.error != null) return Text(data.error.toString());
            accountsCombinerResult =data;
            return _buildWidget;
         ,
      ),
    );

class AccountsCombinerResult 
  final DeleteAccountResultBlocModel deleteAccountResultBlocModel;
  final List<AccountDatabaseModel> accountsList;
  final dynamic error;

  AccountsCombinerResult(
    @required this.accountsList,
    @required this.deleteAccountResultBlocModel,
    this.error,
  );

代码未经过测试,因此可能存在拼写错误或我遗漏的内容,但您应该大致了解。

【讨论】:

它不再工作了... StreamProvider 不在flutter/material.dart 包中。 StreamProvider 也是未定义的对象。我尝试了第一个选项,但它不再起作用了。 不起作用没有帮助,StreamProvider 来自提供程序包,您需要将其添加到您的pubspec.yaml 我遇到同样的问题,打印(“我的帐户列表:$accountList == null”);这条线没有触发。在 StreamProvider 上没有创建参数。我猜你正在使用旧版本。我的结果是一样的。 我刚刚注意到您删除的流可能没有项目,combineLatest 需要在结果流发出之前发出每个源流。 您可能希望使用BehaviorSubject.seeded(null) 而不是PublishSubject + add(null)

以上是关于Rxdart combinelaststream 功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 中的 rxdart 使用未被识别

RxDart框架学习

使用 rxDart 合并 Firestore 流

Observable 在 rxdart 0.23.1 中已弃用

如何在颤振中降级 rxdart 插件?

Flutter 使用流“RxDart”提交登录 Bloc