在BLOC事件后Streambuilder无法重建

如何解决在BLOC事件后Streambuilder无法重建

我正在尝试在我的应用程序中实现分页,但是没有成功。

我正在使用Firebase,特别是具有BLOC模式的Firestore,以及我最近开始使用的“内置价值”来简化分页。

我非常感谢任何帮助或推荐链接如何一起使用这些技术。

我的应用程序体系结构如下:

Application Architecture

我试图尽可能地保持BLOC模式,但这反过来又使得很难进行大量分页,因为将内置值用作内置值使得使用流和期货真的很困难。我在Internet上四处查看,但找不到任何教程或文档来专门使用Firestore和BLOC的内置值进行分页。

问题是,当我执行任何CRUD功能(例如,从列表中删除类别)时,尽管分页和其他所有功能正常工作,Stream Builder都不会更新列表。

当前,我尝试单独使用一个Listview构建器,该构建器显然根本不起作用,因此我移至Stream Builder,并尝试了Streams和Futures(.asStream),但未更新。

下面是一些代码:

模型:

abstract class CategoryCard
    implements Built<CategoryCard,CategoryCardBuilder> {
  String get category;
  String get icon;
  double get budget;
  double get spent;
  String get categoryRef;
  DocumentSnapshot get document;

  CategoryCard._();

  factory CategoryCard([updates(CategoryCardBuilder b)]) = _$CategoryCard;

  static Serializer<CategoryCard> get serializer => _$categoryCardSerializer;
}

查询:

  Future<Stream<fs.QuerySnapshot>> getMoreCategoryAmounts(
      fs.DocumentSnapshot documentSnapshot) async {
    var user = await getCurrentUser();

    print(currentMonth);

    fs.Query categoryAmountQuery = _instance
        .collection('users')
        .document(user.uid)
        .collection('amounts')
        .where('year',isEqualTo: currentYear)
        .where('month',isEqualTo: currentMonth)
        .orderBy('category',descending: false)
        .limit(7);

    return documentSnapshot != null
        ? categoryAmountQuery.startAfterDocument(documentSnapshot).snapshots()
        : categoryAmountQuery.snapshots();
  }

BLOC:

class CategoryCardBloc extends Bloc<CategoryCardEvents,CategoryCardState> {
  final BPipe bPipe;
  final FirebaseRepository firebaseRepository;

  CategoryCardBloc({@required this.bPipe,@required this.firebaseRepository})
      : assert(bPipe != null),assert(firebaseRepository != null);

  @override
  CategoryCardState get initialState => CategoryCardState.intial();

  @override
  Stream<CategoryCardState> mapEventToState(CategoryCardEvents event) async* {
    if (event is LoadCategoryCardEvent) {
      yield* _mapToEventLoadCategoryCard(event);
    }
  }

  Stream<CategoryCardState> _mapToEventLoadCategoryCard(
      LoadCategoryCardEvent event) async* {
    if (event.amountDocumentSnapshot == null) {
      yield CategoryCardState.loading();
    }
    try {
      Future<BuiltList<CategoryCard>> _newCategoryCards =
          bPipe.getMoreCategoryCards(event.amountDocumentSnapshot);

      yield CategoryCardState.loaded(
          FutureMerger()
              .merge<CategoryCard>(state.categoryCards,_newCategoryCards));
    } on NullException catch (err) {
      print('NULL_EXCEPTION');
      yield CategoryCardState.failed(err.objectExceptionMessage,state?.categoryCards ?? Stream<BuiltList<CategoryCard>>.empty());
    } on NoValueException catch (_) {
      print('NO VALUE EXCEPTION');
      yield state.rebuild((b) => b..hasReachedEndOfDocuments = true);
    } catch (err) {
      print('UNKNOWN EXCEPTION');
      yield CategoryCardState.failed(
          err != null ? err.toString() : NullException.exceptionMessage,state.categoryCards);
    }
  }
}

国家:

abstract class CategoryCardState
    implements Built<CategoryCardState,CategoryCardStateBuilder> {
  Future<BuiltList<CategoryCard>> get categoryCards;
  //*Reached end indicator
  bool get hasReachedEndOfDocuments;
  //*Error state
  String get exception;
  //*Loading state
  @nullable
  bool get isLoading;
  //*Success state
  @nullable
  bool get isSuccessful;
  //*Loaded state
  @nullable
  bool get isLoaded;

  CategoryCardState._();

  factory CategoryCardState([updates(CategoryCardStateBuilder b)]) =
      _$CategoryCardState;

  factory CategoryCardState.intial() {
    return CategoryCardState((b) => b
      ..exception = ''
      ..isSuccessful = false
      ..categoryCards =
          Future<BuiltList<CategoryCard>>.value(BuiltList<CategoryCard>())
      ..hasReachedEndOfDocuments = false);
  }

  factory CategoryCardState.loading() {
    return CategoryCardState((b) => b
      ..exception = ''
      ..categoryCards =
          Future<BuiltList<CategoryCard>>.value(BuiltList<CategoryCard>())
      ..hasReachedEndOfDocuments = false
      ..isLoading = true);
  }
  factory CategoryCardState.loaded(Future<BuiltList<CategoryCard>> cards) {
    return CategoryCardState((b) => b
      ..exception = ''
      ..categoryCards = cards
      ..hasReachedEndOfDocuments = false
      ..isLoading = false
      ..isLoaded = true);
  }
  factory CategoryCardState.success(Future<BuiltList<CategoryCard>> cards) {
    return CategoryCardState((b) => b
      ..exception = ''
      ..categoryCards =
          Future<BuiltList<CategoryCard>>.value(BuiltList<CategoryCard>())
      ..hasReachedEndOfDocuments = false
      ..isSuccessful = true);
  }
  factory CategoryCardState.failed(
      String exception,Future<BuiltList<CategoryCard>> cards) {
    return CategoryCardState((b) => b
      ..exception = exception
      ..categoryCards = cards
      ..hasReachedEndOfDocuments = false);
  }
}

事件:

abstract class CategoryCardEvents extends Equatable {}

class LoadCategoryCardEvent extends CategoryCardEvents {
  final DocumentSnapshot amountDocumentSnapshot;

  LoadCategoryCardEvent({@required this.amountDocumentSnapshot});

  @override
  List<Object> get props => [amountDocumentSnapshot];
}

分页屏幕(包含在有状态的小部件中):

//Notification Handler
  bool _scrollNotificationHandler(
      ScrollNotification notification,DocumentSnapshot amountDocumentSnapshot,bool hasReachedEndOfDocuments,Future<BuiltList<CategoryCard>> cards) {
    if (notification is ScrollEndNotification &&
        _scollControllerHomeScreen.position.extentAfter == 0 &&
        !hasReachedEndOfDocuments) {
      setState(() {
        _hasReachedEnd = true;
      });

      _categoryCardBloc.add(LoadCategoryCardEvent(
          amountDocumentSnapshot: amountDocumentSnapshot));
    }
    return false;
  }


BlocListener<CategoryCardBloc,CategoryCardState>(
                    bloc: _categoryCardBloc,listener: (context,state) {
                      if (state.exception != null &&
                          state.exception.isNotEmpty) {
                        if (state.exception == NullException.exceptionMessage) {
                          print('Null Exception');
                        }  else {
                          ErrorDialogs.customAlertDialog(
                              context,'Failed to load','Please restart app or contact support');

                          print(state.exception);
                        }
                      }
                    },child: BlocBuilder<CategoryCardBloc,CategoryCardState>(
                        bloc: _categoryCardBloc,builder: (context,state) {
                          if (state.isLoading != null && state.isLoading) {
                            return Center(
                              child: CustomLoader(),);
                          }

                          if (state.isLoaded != null && state.isLoaded) {
                            return StreamBuilder<BuiltList<CategoryCard>>(
                              stream: state.categoryCards.asStream(),snapshot) {

                                if (!snapshot.hasData) {
                                  return Center(
                                    child: CustomLoader(),);
                                } else {
                                  BuiltList<CategoryCard> categoryCards =
                                      snapshot.data;

                                  _hasReachedEnd = false;

                                  print(state.hasReachedEndOfDocuments &&
                                      state.hasReachedEndOfDocuments != null);

                                  return Container(
                                    height: Mquery.screenHeight(context),width: Mquery.screenWidth(context),child: NotificationListener<
                                        ScrollNotification>(
                                      onNotification: (notification) =>
                                          _scrollNotificationHandler(
                                              notification,categoryCards.last.document,state.hasReachedEndOfDocuments,state.categoryCards),child: SingleChildScrollView(
                                        controller: _scollControllerHomeScreen,child: Column(
                                          children: [
                                            CustomAppBar(),Padding(
                                              padding: EdgeInsets.all(
                                                  Mquery.padding(context,2.0)),child: Row(
                                                children: [
                                                  Expanded(
                                                    flex: 5,child: Padding(
                                                      padding: EdgeInsets.all(
                                                          Mquery.padding(
                                                              context,1.0)),child:Container(
                                                          width: Mquery.width(
                                                              context,50.0),height: Mquery.width(
                                                              context,12.5),decoration:
                                                              BoxDecoration(
                                                            color: middle_black,borderRadius: BorderRadius
                                                                .circular(Constants
                                                                    .CARD_BORDER_RADIUS),boxShadow: [
                                                              BoxShadow(
                                                                  color: Colors
                                                                      .black54,blurRadius:
                                                                      4.0,spreadRadius:
                                                                      0.5)
                                                            ],),child: Padding(
                                                            padding: EdgeInsets.fromLTRB(
                                                                Mquery.padding(
                                                                    context,4.0),Mquery.padding(
                                                                    context,2.0),child: TextField(
                                                              textInputAction:
                                                                  TextInputAction
                                                                      .done,style: TextStyle(
                                                                  color: white,fontSize: Mquery
                                                                      .fontSize(
                                                                          context,4.25)),controller:
                                                                  searchController,decoration:
                                                                  InputDecoration(
                                                                border:
                                                                    InputBorder
                                                                        .none,hintText: Constants
                                                                    .SEARCH_MESSAGE,hintStyle: TextStyle(
                                                                    fontSize: Mquery
                                                                        .fontSize(
                                                                            context,4.25),color:
                                                                        white),Expanded(
                                                      flex: 1,child: Padding(
                                                        padding: EdgeInsets.all(
                                                            Mquery.padding(
                                                                context,child: Container(
                                                          decoration:
                                                              BoxDecoration(
                                                            boxShadow: [
                                                              BoxShadow(
                                                                  color: Colors
                                                                      .black54,color: middle_black,width: Mquery.width(
                                                              context,child: IconButton(
                                                            splashColor: Colors
                                                                .transparent,highlightColor:
                                                                Colors
                                                                    .transparent,icon: Icon(
                                                              Icons.search,color: white,onPressed: () {
                                                              _onSearchButtonPressed();
                                                            },))
                                                ],ListView.builder(
                                              shrinkWrap: true,itemCount: categoryCards.length,physics:
                                                  NeverScrollableScrollPhysics(),itemBuilder: (context,index) {
                                                return GestureDetector(
                                                    onTap: () {
                                                      //Navigate
                                                    },child:
                                                        CategoryCardWidget(
                                                            categoryCount:
                                                                categoryCards
                                                                    .length,categoryCard:
                                                                categoryCards[
                                                                    index]));
                                              },_hasReachedEnd
                                                ? Padding(
                                                    padding: EdgeInsets.all(
                                                        Mquery.padding(
                                                            context,4.0)),child: CustomLoader(),)
                                                : Container()
                                          ],);
                                }
                              },);
                          }

                          return Container();
                        }))

感谢您的时间,并很抱歉如此冗长

  • 马特

解决方法

我设法解决了这个问题,

下面是Github链接: https://github.com/felangel/bloc/issues/1707

希望对某人有帮助! -马特

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-