【问题标题】:how to use infinite_scroll_pagination for bloc pattern如何将infinite_scroll_pagination 用于块模式
【发布时间】: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,
          ),
        ),
      ),),
      );
  }

【问题讨论】:

标签: flutter infinite-scroll bloc


【解决方案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,我认为这就是告诉它停止获取记录的原因?我还编辑了我的问题并包含了修改后的代码。
  • 是的...我也注意到那里..所以你必须从后端获取最后一页..就像最后一个页码...
猜你喜欢
  • 2023-04-05
  • 2022-10-19
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2016-07-15
  • 1970-01-01
  • 2018-01-28
  • 1970-01-01
相关资源
最近更新 更多