首页 > 解决方案 > 如何将infinite_scroll_pagination 用于块模式

问题描述

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

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

这是我的集团脚本:

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,
          ),
        ),
      ),),
      );
  }

标签: flutterinfinite-scrollbloc

解决方案


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),
    );
  }

是的,这个方法对我有用


推荐阅读