QuirijnGB / lazy-load-scrollview

A wrapper for a Flutter ScrollView which enables lazy loading
BSD 2-Clause "Simplified" License
108 stars 26 forks source link

CustomScrollView implementation #14

Closed Slaine066 closed 3 years ago

Slaine066 commented 3 years ago

Does it work with CustomScrollView and related SliverList? I wrapped the CustomScrollView with the LazyLoadScrollView, but I can only obtain the first pagination. After that the onEndOfPage method does not get called anymore.

QuirijnGB commented 3 years ago

It should! I have it implemented in a similar way and it works. Do you have some code?

Slaine066 commented 3 years ago

Here!

LazyLoadScrollView(
          scrollOffset: 300,
          onEndOfPage: () {
            // Pagination
            BlocProvider.of<DiscussionFeedBloc>(context).add(
              DiscussionFeedFetchMoreCmd(
                userId: widget.user.id,
                categoryIds: BlocProvider.of<DiscussionFeedBloc>(context).state.discussionFeed.selectedSubCategory,
                sortType: BlocProvider.of<DiscussionFeedBloc>(context).state.discussionFeed.selectedSorting,
                offset: BlocProvider.of<DiscussionFeedBloc>(context).state.discussionFeed.discussionList.length,
              ),
            );
          },
          child: CustomScrollView(
            controller: scrollController,
            key: PageStorageKey<String>(widget.discussionCategory.label),
            slivers: <Widget>[
              // Sub Categories
              SliverAppBar(),

              // Search Bar
              SliverAppBar(),

              // Sort Bar
              SliverAppBar(),

              // Pull To Refresh
              CupertinoSliverRefreshControl(
                onRefresh: () {
                  BlocProvider.of<DiscussionFeedBloc>(context).add(
                    DiscussionFeedRefreshCmd(
                      userId: widget.user.id,
                      categoryIds:
                          BlocProvider.of<DiscussionFeedBloc>(context).state.discussionFeed.selectedSubCategory,
                      sortType: BlocProvider.of<DiscussionFeedBloc>(context).state.discussionFeed.selectedSorting,
                    ),
                  );

                  return refreshCompleter.future;
                },
              ),

              // Discussion List
              BlocBuilder<DiscussionFeedBloc, DiscussionFeedState>(
                builder: (context, state) {
                  // First Fetch or Pagination Fetch
                  if (state.status == DiscussionFeedStatus.fetching_success ||
                      state.status == DiscussionFeedStatus.fetching_more_in_progress) {
                    refreshCompleter?.complete();
                    refreshCompleter = Completer<void>();
                    // If Not Empty
                    if (state.discussionFeed.discussionList.isNotEmpty) {
                      return SliverList(
                        delegate: SliverChildBuilderDelegate(
                          (BuildContext context, int index) {
                            final int itemIndex = index ~/ 2;

                            if (index.isOdd) {
                              return pickyThickDivider(color: PickyColors.gray50);
                            }
                            return DiscussionCard(
                              discussion: state.discussionFeed.discussionList[itemIndex],
                              userId: widget.user.id,
                              firebaseId: widget.user.firebaseUid,
                            );
                          },
                          childCount: (state.discussionFeed.discussionList.length * 2) - 1,
                        ),
                      );
                    }

                    // If Empty
                    else {
                      return SliverFillRemaining(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Image.asset(
                              'assets/emptyPostIcon@3x.png',
                              height: 50,
                              width: 40,
                            ),
                            SizedBox(height: PickyHorizontalMargins),
                            Text(
                              'There are no discussions yet!',
                              style: PickyTypographies.display5(color: PickyColors.gray600),
                            ),
                          ],
                        ),
                      );
                    }
                  }

                  // Fetching Failure
                  else if (state.status == DiscussionFeedStatus.fetching_failure) {
                    refreshCompleter?.complete();
                    refreshCompleter = Completer<void>();

                    return SliverFillRemaining(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Image.asset(
                            'assets/pickyGirl-disappoint@3x.png',
                            height: 124,
                            width: 82,
                          ),
                          Text(
                            'Error occured.\nPlease try again!',
                            style: PickyTypographies.display5(color: PickyColors.gray600),
                            textAlign: TextAlign.center,
                          ),
                        ],
                      ),
                    );
                  }

                  // Refresh In Progress
                  else if (state.status == DiscussionFeedStatus.refresh_in_progress) {
                    return SliverFillRemaining(child: Container());
                  }

                  // Fetching In Progress
                  else {
                    return SliverFillRemaining(child: LoadingComponent());
                  }
                },
              ),
            ],
          ),
        )
QuirijnGB commented 3 years ago

I have a BlocBuilder as a parent of the LazyScrollView, so that explains why it works for me since it'll rebuild entirely, arguably not what you'd want. Ill have a look if I can make it work the way you have it.

Slaine066 commented 3 years ago

Thank you man. Let me know!

QuirijnGB commented 3 years ago

Reason it wont load more is because internally it still thinks that content is being loaded, because you're not using isLoading on the LazyLoadScrollView. It needs a trigger to tell it its no longer loading. If I remove that state, you'll get spammed with endOfPage notifications.

I cant think of any solution other than moving the BlocBuilder up the tree. Unless you have any ideas 😅

Slaine066 commented 3 years ago

I wrapped the LazyLoadScrollView with the BlocBuilder and it's working fine now. Thanks!