如何将infinite_scroll_pagination 用于块模式

Posted

技术标签:

【中文标题】如何将infinite_scroll_pagination 用于块模式【英文标题】:how to use infinite_scroll_pagination for bloc pattern 【发布时间】:2021-08-22 06:24:28 【问题描述】:

我目前正在学习并将我的代码转换为 BLoc 模式。在我使用flutter_pagewise ^1.2.3 进行无限滚动之前,我使用Future<>,但我不知道如何使用 bloc 或者它是否与它兼容。

所以现在我正在尝试infinite_scroll_pagination: ^2.3.0,因为它在其文档中说它支持 Bloc。但我不理解 bloc 文档中的示例代码。你能给我一个简单的例子来说明如何将它与 bloc 一起使用吗?我目前正在使用flutter_bloc:^6.1.3。

这是我的 bloc 脚本:

class TimeslotViewBloc extends Bloc<TimeslotViewEvent, TimeslotViewState> 
  final GetTimeslotView gettimeslotView;

  TimeslotViewBloc(this.gettimeslotView) : super(TimeslotViewInitialState());

  @override
  Stream<TimeslotViewState> mapEventToState(
    TimeslotViewEvent event,
  ) async* 
    if (event is GetTimeslotViewEvent) 
      yield TimeslotViewLoadingState();
      final failureOrSuccess = await gettimeslotView(Params(
        id: event.id,
        date: event.date,
      ));
      yield* _eitherLoadedOrErrorState(failureOrSuccess);
    
  

  Stream<TimeslotViewState> _eitherLoadedOrErrorState(
    Either<Failure, List<TimeslotViewEntity>> failureOrTrivia,
  ) async* 
    yield failureOrTrivia.fold(
      (failure) => TimeslotViewErrorState(
          message: _mapFailureToMessage(failure), failure: failure),
      (result) => TimeslotViewLoadedState(result),
    );
  


//Bloc Events----------------------------------------
abstract class TimeslotViewEvent extends Equatable 
  const TimeslotViewEvent();
  @override
  List<Object> get props => [];


class GetTimeslotViewEvent extends TimeslotViewEvent 
  final String id;
  final String date;
  final int offset;
  final int limit;

  GetTimeslotViewEvent(
      this.id,
      this.date,
      this.offset,
      this.limit);


//Bloc States----------------------------------------
abstract class TimeslotViewState extends Equatable 
  const TimeslotViewState();
  @override
  List<Object> get props => [];


class TimeslotViewLoadingState extends TimeslotViewState 

class TimeslotViewLoadedState extends TimeslotViewState 
  final List<TimeslotViewEntity> records;

  TimeslotViewLoadedState(this.records);
  @override
  List<Object> get props => [records];

更新:这是适用于我的 Davii 修改后的代码

@override
  Widget build(BuildContext context) 
    return BlocProvider(
      create: (context) => _timeLotBloc,
      child: BlocListener<TimeslotViewBloc, TimeslotViewState>(
        listener: (context, state) 
          if (state is TimeslotViewLoadedState) 

            //Save record count instead of records list
            totalRecordCount += state.records.length; 
            final _next = 1 + totalRecordCount;

            final isLastPage = state.records.length < PAGE_SIZE;
            if (isLastPage) 
              _pagingController.appendLastPage(state.records);
             else 
              _pagingController.appendPage(state.records, _next);
            
          
          if (state is TimeslotViewErrorState) 
            _pagingController.error = state.error;
          
          
        ,
        //Removed pagedListview from bloc builder
        child: PagedListView<int, TimeslotViewEntity>(
            pagingController: _pagingController,
            builderDelegate: PagedChildBuilderDelegate<TimeslotViewEntity>(
            itemBuilder: (context, time, index) => TimeslotViewEntityListItem(
            character: time,
          ),
        ),
      ),),
      );
  

【问题讨论】:

我已经在我的一个原型项目中实现了无限滚动,没有任何包:github.com/mkobuolys/shopping-app-prototype 检查 modules/products/bloc/products_bloc.dart 以获取 BLoC 示例,modules/products/widgets/products_list_view.dart 获取使用示例。如果您需要任何说明,请告诉我。 以防万一有人在使用flutter_bloc包,这里是官方教程:bloclibrary.dev/#/flutterinfinitelisttutorial 【参考方案1】:
class PaginatedList extends StatefulWidget 
  const PaginatedList(Key? key) : super(key: key);

  @override
  _PaginatedListState createState() => _PaginatedListState();


class _PaginatedListState extends State<PaginatedList> 
  //*bloc assuming you use getIt and injectable
  late final _timeLotBloc = getIt<TimeslotViewBloc>();

  List<TimeslotViewEntity> records = [];

  //*initialize page controller
  final PagingController<int, TimeslotViewEntity> _pagingController =
      PagingController(firstPageKey: 0);

  @override
  void initState() 
    super.initState();

    //*so at event add list of records
    _pagingController.addPageRequestListener(
      (pageKey) => _timeLotBloc
          .add(GetTimeslotViewEvent(records: records, offset: pageKey,limit: 10)),
    );
  

  @override
  void dispose() 
    super.dispose();
    _timeLotBloc.close();
    _pagingController.dispose();
  

  @override
  Widget build(BuildContext context) 
    return BlocProvider(
      create: (context) => _timeLotBloc,
      child: BlocListener<TimeslotViewBloc, TimeslotViewState>(
        listener: (context, state) 
          if (state is TimeslotViewLoadedState) 

            records =state.records;
          
            //forget about existing record
            //about the last page, fetch last page number from 
            //backend

            int lastPage = state.lastPage
            final _next = 1 + records.length;

            if(_next>lastPage)
              _pagingController.appendLastPage(records);
              
            else
               _pagingController.appendPage(records, _next);
            
            
            
          
          if (state is TimeslotViewErrorState) 
            _pagingController.error = state.error;
          
          
        ,child: BlocBuilder<TimeslotViewBloc,TimeslotViewState>(
          builder: (context,state)=> PagedListView<int, TimeslotViewEntity>(
            pagingController: _pagingController,
            builderDelegate: PagedChildBuilderDelegate<TimeslotViewEntity>(
            itemBuilder: (context, time, index) => TimeslotViewEntityListItem(
            character: time,
          ),
        ),
      ),),
      ),
    );
  

现在在集团事件类

class GetTimeslotViewEvent extends TimeslotViewEvent 
  final String id;
  final String date;
  final int offset;
  final int limit;
  //add this on event
  final List<TimeslotViewEntity> records;

  GetTimeslotViewEvent(
    this.id,
    this.date,
    this.offset,
    this.limit,
    required this.records,
  );

关于状态类

class TimeslotViewLoadedState extends TimeslotViewState 
  final List<TimeslotViewEntity> records;
  final List<TimeslotViewEntity> existingRecords;
  TimeslotViewLoadedState(this.records, this.existingRecords);
  @override
  List<Object> get props => [records, existingRecords];

现在就在集团内

 yield* _eitherLoadedOrErrorState(failureOrSuccess,event);
  Stream<TimeslotViewState> _eitherLoadedOrErrorState(
    Either<Failure, List<TimeslotViewEntity>> failureOrTrivia,
    GetTimeslotViewEvent event,
  ) async* 
    yield failureOrTrivia.fold(
      (failure) => TimeslotViewErrorState(
          message: _mapFailureToMessage(failure), failure: failure),
          //existing records from the event,
      (result) => TimeslotViewLoadedState(result,event.records),
    );
  

这个方法对我有用

【讨论】:

感谢您的示例代码。我已经尝试过您的代码,但向下滚动时从 API 获取记录并没有停止。我已经编辑了 PaginateList 页面,并从 bloc builder 中删除了 PageListView。我还添加了addLastPage,我认为这就是告诉它停止获取记录的原因?我还编辑了我的问题并包含了修改后的代码。 是的...我也注意到那里..所以你必须从后端获取最后一页..就像最后一个页码...

以上是关于如何将infinite_scroll_pagination 用于块模式的主要内容,如果未能解决你的问题,请参考以下文章

如何将Ios文件上传到

Qt如何将文字变成图片?

如何将Bitmap保存为本地图片文件?

在MATLAB中如何将图导出

ASP如何将SQLSERVER数据导出到DBF(VF)

如何将CSV格式转换成JSON格式