EdsonBueno / infinite_scroll_pagination

Flutter package to help you lazily load and display pages of items as the user scrolls down your screen.
https://pub.dev/packages/infinite_scroll_pagination
MIT License
629 stars 214 forks source link

_pagingController does not disposes properly #64

Closed Nulligma closed 3 years ago

Nulligma commented 3 years ago

If I use a TabBar and both tabs have infinite scroll then if I switch tabs between pages are getting fetched then I following error

Restarted application in 268ms.
Error: Exception: A PagingController was used after being disposed.
Once you have called dispose() on a PagingController, it can no longer be used.
If you’re using a Future, it probably completed after the disposal of the owning widget.
Make sure dispose() has not been called yet before using the PagingController.
    at Object.throw_ [as throw] (http://localhost:60320/dart_sdk.js:5032:11)
    at http://localhost:60320/packages/infinite_scroll_pagination/src/core/paging_controller.dart.lib.js:122:23
    at PagingController.new.[_debugAssertNotDisposed] (http://localhost:60320/packages/infinite_scroll_pagination/src/core/paging_controller.dart.lib.js:125:27)
    at PagingController.new.notifyStatusListeners (http://localhost:60320/packages/infinite_scroll_pagination/src/core/paging_controller.dart.lib.js:140:53)
    at PagingController.new.set value [as value] (http://localhost:60320/packages/infinite_scroll_pagination/src/core/paging_controller.dart.lib.js:92:16)
    at PagingController.new.set error [as error] (http://localhost:60320/packages/infinite_scroll_pagination/src/core/paging_controller.dart.lib.js:79:20)
    at twitch_infiniteList.__CategoryListState.new._fetchPage (http://localhost:60320/packages/twitch_clone/components/twitch_infiniteList.dart.lib.js:3617:43)
    at _fetchPage.next (<anonymous>)
    at http://localhost:60320/dart_sdk.js:37210:33
    at _RootZone.runUnary (http://localhost:60320/dart_sdk.js:37081:59)
    at _FutureListener.thenAwait.handleValue (http://localhost:60320/dart_sdk.js:32337:29)
    at handleValueCallback (http://localhost:60320/dart_sdk.js:32864:49)

I dont get any error if I wait for page to fetch

I tried removing Listener but still get the same error

  @override
  void dispose() {
    _pagingController.removePageRequestListener(_fetchPage);
    _pagingController.dispose();
    super.dispose();
  }
michael-woolsey commented 3 years ago

I'm having a similar problem, I also tried removePageRequestListener() and it didn't help me either.

EdsonBueno commented 3 years ago

Hi @Nulligma and @michael-woolsey . The solution to your problem is detailed here: https://github.com/EdsonBueno/infinite_scroll_pagination/pull/7 Thank you, feel free to ping me in our chat if you still have any problems.

Rissmon commented 3 years ago

I added the below condition check immediately after Future call

if (mounted) {
}

  Future<void> _fetchPage(int pageKey) async {
    final pageSize = 10;

    final newItems = await RemoteAPI.getFoosByStatus(
      widget.status,
      limit: pageSize,
      offset: pageKey,
    );
if (mounted) {
    final isLastPage = newItems.length < pageSize;
    if (isLastPage) {
      _pagingController.appendLastPage(newItems);
    } else {
      final nextPageKey = pageKey + newItems.length;
      _pagingController.appendPage(newItems, nextPageKey);
    }}
  }

This worked for me.. Hope it will help someone

vgavrilovikj commented 7 months ago

what happens in case where the pagingController is inside a BLoC, how to dispose it then..

void onFindAll(GetReservationsFindAll getReservationsFindAll,
      Emitter<ReservationsFindAllState> emit) async {
    emit(const ReservationsLoading());
    String? nextStartDate;
    ReservationsFindAllDto? reservationsFindAllDto =
        getReservationsFindAll.reservationsFindAllDto;

    if (getReservationsFindAll.isFilterClicked != null &&
        getReservationsFindAll.isFilterClicked! == true) {
      resetPageController();
    } else {
      nextStartDate = await _secureStorage.getReservationsNextStartDate();
    }

    ReservationsFindAllDto? newReservationsFindAllDto = ReservationsFindAllDto(
        filterReservationsEnum: reservationsFindAllDto?.filterReservationsEnum,
        limit: reservationsFindAllDto?.limit,
        page: reservationsFindAllDto?.page ?? 1,
        nextStartDate: nextStartDate);

    final dataState =
        await _findAllUseCase.call(params: newReservationsFindAllDto);

    if (dataState is DataSuccess) {
      final newData = dataState.data!;
      final isLastPage = newData.reservations!.isEmpty;
      final int page =
          getReservationsFindAll.reservationsFindAllDto?.page != null
              ? getReservationsFindAll.reservationsFindAllDto!.page
              : 1;

      if (isLastPage) {
        _pagingController.appendLastPage(newData.reservations!);
      } else {
        _pagingController.appendPage(newData.reservations!, page + 1);
      }

      emit(ReservationsLoaded(newData.reservations!));
    }

    if (dataState is DataFailed) {
      emit(ReservationsError(dataState.exception!));
    }
  }
clragon commented 7 months ago

Blocs have the close method that you can override to dispose of state.

Please do not necro in old issues. Thank you.