flutter 如何防止API在scroll控制器上被多次调用

sxpgvts3  于 2023-02-20  发布在  Flutter
关注(0)|答案(1)|浏览(151)

我有一个滚动控制器。当滚动位置超过一个定义的值时,我会发出一个请求。问题是,当它超过这个位置时,它会发出数千个请求。为了防止这种情况,我尝试实现一个加载,但它似乎不起作用。
这是我的滚动控制器

@override
  void initState() {
    super.initState();
    PetsBloc petsBloc = BlocProvider.of<PetsBloc>(context);
    _scrollController.addListener(() {
      final ScrollPosition position = _scrollController.position;
      if (position.pixels >= position.maxScrollExtent - 500 &&
          selectedView.isNotEmpty &&
          !petsBloc.state.loading) {
        //* Make the requeset
        petsBloc.add(CollectionRequested(collection, page));
        setState(() {
          page++;
        });
      }
    });
  }

这是我的pets_bloc.dart

class PetsBloc extends Bloc<PetsEvent, PetsState> {
  PetsRepository petsRepository = PetsRepository();
  AlertsRepository alertsRepository = AlertsRepository();
  InfoRepository infoRepository = InfoRepository();

  PetsBloc() : super(const PetsState()) {
    on<CollectionRequested>((event, emit) async {
      if (!state.loading) {
        emit(state.copyWith(loading: true));
        final List<PetModel> result =
            await petsRepository.getCollection(event.collection, event.page * 10);
        switch (event.collection) {
          case 'lost':
            emit(state.copyWith(lostPets: [...state.lostPets, ...result]));
            break;
          case 'transit':
            emit(state.copyWith(foundPets: [...state.foundPets, ...result]));
            break;
          case 'adoption':
            emit(state.copyWith(adoptionPets: [...state.adoptionPets, ...result]));
            break;
        }
      }
    });
  }
}

这是我的pets_state.dart

part of 'pets_bloc.dart';

class PetsState extends Equatable {
  final List<PetModel> lostPets;
  final List<PetModel> adoptionPets;
  final List<PetModel> foundPets;
  final List<AlertModel> alertPets;
  final List<UserPost> userPosts;
  final bool loading;
  final bool fetched;

  const PetsState({
    this.lostPets = const [],
    this.adoptionPets = const [],
    this.foundPets = const [],
    this.alertPets = const [],
    this.userPosts = const [],
    this.loading = false,
    this.fetched = false,
  });

  PetsState copyWith({
    List<PetModel>? lostPets,
    List<PetModel>? adoptionPets,
    List<PetModel>? foundPets,
    List<AlertModel>? alertPets,
    List<UserPost>? userPosts,
    bool? loading,
    bool? fetched,
  }) =>
      PetsState(
        lostPets: lostPets ?? this.lostPets,
        adoptionPets: adoptionPets ?? this.adoptionPets,
        foundPets: foundPets ?? this.foundPets,
        alertPets: alertPets ?? this.alertPets,
        userPosts: userPosts ?? this.userPosts,
        loading: loading ?? this.loading,
        fetched: fetched ?? this.fetched,
      );

  @override
  List<Object> get props => [lostPets, adoptionPets, foundPets, alertPets, userPosts];
}

即使在initstate中以及在if(!state.loading)上的中有一个if,但仍会发出请求
我希望你能帮助我!先谢了!

km0tfn4u

km0tfn4u1#

Here您可以找到一个官方示例,说明如何限制事件,以便在短时间内只触发一个事件。
主要思想是实现一个自定义事件转换器:

EventTransformer<E> throttleDroppable<E>(Duration duration) {
  return (events, mapper) {
    return droppable<E>().call(events.throttle(duration), mapper);
  };
}

请注意,您需要将一个bloc_concurrency包添加到项目依赖项中。
然后,在您的块中使用此事件转换器:

class PetsBloc extends Bloc<PetsEvent, PetsState> {
  PetsRepository petsRepository = PetsRepository();
  AlertsRepository alertsRepository = AlertsRepository();
  InfoRepository infoRepository = InfoRepository();

  PetsBloc() : super(const PetsState()) {
    on<CollectionRequested>((event, emit) async {
      if (!state.loading) {
        emit(state.copyWith(loading: true));
        final List<PetModel> result =
            await petsRepository.getCollection(event.collection, event.page * 10);
        switch (event.collection) {
          case 'lost':
            emit(state.copyWith(lostPets: [...state.lostPets, ...result]));
            break;
          case 'transit':
            emit(state.copyWith(foundPets: [...state.foundPets, ...result]));
            break;
          case 'adoption':
            emit(state.copyWith(adoptionPets: [...state.adoptionPets, ...result]));
            break;
        }
      }
    },
    transformer: throttleDroppable(Duration(milliseconds: 100)), // Use the new transformer
    );
  }
}

此时,100毫秒内的所有事件都将被忽略,只有一个事件将被激发。请根据需要调整此持续时间值。

相关问题