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
634 stars 215 forks source link

Exception only when using RefreshIndicator #44

Closed Purus closed 3 years ago

Purus commented 3 years ago

When using the RefreshIndicator am getting the below exception. If I remove the RefreshIndicator widget, all works fine as expected. The widget shown below is used in other widgets which uses CustomScrollView.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:womenly/models/post_model.dart';
import 'package:womenly/services/firestore_database.dart';
import 'package:womenly/widgets/single_post_card.dart';

class PostsList extends StatefulWidget {
  final bool showOnlyFav;
  final bool showPopular;
  final String userId;
  final String label;
  final String category;
  final String favUserId;

  PostsList({
    this.showOnlyFav = false,
    this.showPopular = false,
    this.userId,
    this.category,
    this.label,
    this.favUserId,
  });

  @override
  _PostsListState createState() => _PostsListState();
}

class _PostsListState extends State<PostsList>
    with AutomaticKeepAliveClientMixin<PostsList> {
  static const _pageSize = 4;
  DocumentSnapshot lastDoc;

  final PagingController<int, QueryDocumentSnapshot> _pagingController =
      PagingController(firstPageKey: 0);

  @override
  void initState() {
    _pagingController.addPageRequestListener((pageKey) {
      _fetchPage(pageKey);
    });
    super.initState();
  }

  @override
  void dispose() {
    _pagingController.dispose();
    super.dispose();
  }

  Future<void> _fetchPage(int pageKey) async {
    try {
      final querySnapshot = await FirestoreDatabase().postsStream(
          favUserId: widget.favUserId,
          category: widget.category,
          userId: widget.userId,
          label: widget.label,
          lastDoc: lastDoc,
          count: _pageSize,
          showPopular: widget.showPopular,
          showOnlyFav: widget.showOnlyFav);

      List<QueryDocumentSnapshot> docs = querySnapshot.docs;

      final isLastPage = docs.length < _pageSize;
      lastDoc = docs.last;

      if (isLastPage) {
        _pagingController.appendLastPage(docs);
      } else {
        final nextPageKey = pageKey + docs.length;
        _pagingController.appendPage(docs, nextPageKey);
      }
    } catch (error) {
      _pagingController.error = error;
    }
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: () => Future.sync(() => _pagingController.refresh()),
      child: PagedSliverList<int, QueryDocumentSnapshot>(
        pagingController: _pagingController,
        builderDelegate: PagedChildBuilderDelegate<QueryDocumentSnapshot>(
          itemBuilder: (context, item, index) =>
              SingleDesignWidget(PostModel.fromMap(item.data())),
        ),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

Below is the exception.

Performing hot restart...
Syncing files to device Redmi Note 7 Pro...
Restarted application in 2,302ms.
I/flutter (13686): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (13686): The following assertion was thrown building RefreshIndicator(dependencies: [_InheritedTheme,
I/flutter (13686): _EffectiveTickerMode, _LocalizationsScope-[GlobalKey#f827c]], state:
I/flutter (13686): RefreshIndicatorState#4a99c(tickers: tracking 2 tickers)):
I/flutter (13686): A RenderViewport expected a child of type RenderSliver but received a child of type RenderStack.
I/flutter (13686): RenderObjects expect specific types of children because they coordinate with their children during
I/flutter (13686): layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a
I/flutter (13686): RenderSliver does not understand the RenderBox layout protocol.
I/flutter (13686): 
I/flutter (13686): The RenderViewport that expected a RenderSliver child was created by:
I/flutter (13686):   Viewport ← IgnorePointer-[GlobalKey#920d1] ← Semantics ← _PointerListener ← Listener ←
I/flutter (13686):   _GestureSemantics ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#8768b] ←
I/flutter (13686):   _PointerListener ← Listener ← _ScrollableScope ← _ScrollSemantics-[GlobalKey#10bbd] ←
I/flutter (13686):   RepaintBoundary ← ⋯
I/flutter (13686): 
I/flutter (13686): The RenderStack that did not match the expected child type was created by:
I/flutter (13686):   Stack ← RefreshIndicator ← PostsList ← Viewport ← IgnorePointer-[GlobalKey#920d1] ← Semantics ←
I/flutter (13686):   _PointerListener ← Listener ← _GestureSemantics ←
I/flutter (13686):   RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#8768b] ← _PointerListener ← Listener
I/flutter (13686):   ← ⋯
I/flutter (13686): 
I/flutter (13686): The relevant error-causing widget was:
I/flutter (13686):   RefreshIndicator file:///D:/Flutter/womenly/lib/screens/posts/posts_list.dart:83:12
I/flutter (13686): 
I/flutter (13686): When the exception was thrown, this was the stack:
I/flutter (13686): #0      ContainerRenderObjectMixin.debugValidateChild.<anonymous closure> (package:flutter/src/rendering/object.dart:3123:9)
I/flutter (13686): #1      ContainerRenderObjectMixin.debugValidateChild (package:flutter/src/rendering/object.dart:3150:6)
I/flutter (13686): #2      MultiChildRenderObjectElement.insertRenderObjectChild (package:flutter/src/widgets/framework.dart:6191:25)
I/flutter (13686): #3      RenderObjectElement.attachRenderObject (package:flutter/src/widgets/framework.dart:5805:35)
I/flutter (13686): #4      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5501:5)
I/flutter (13686): #5      MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6232:11)
I/flutter (13686): ...     Normal element mounting (17 frames)
I/flutter (13686): #22     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #23     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): #24     _ViewportElement.mount (package:flutter/src/widgets/viewport.dart:225:11)
I/flutter (13686): ...     Normal element mounting (127 frames)
I/flutter (13686): #151    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #152    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (103 frames)
I/flutter (13686): #255    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #256    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (208 frames)
I/flutter (13686): #464    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #465    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (70 frames)
I/flutter (13686): #535    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #536    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (210 frames)
I/flutter (13686): #746    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #747    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (156 frames)
I/flutter (13686): #903    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #904    Element.updateChild (package:flutter/src/widgets/framework.dart:3324:20)
I/flutter (13686): #905    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4652:16)
I/flutter (13686): #906    StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
I/flutter (13686): #907    Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
I/flutter (13686): #908    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2730:33)
I/flutter (13686): #909    WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:913:20)
I/flutter (13686): #910    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
I/flutter (13686): #911    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
I/flutter (13686): #912    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
I/flutter (13686): #913    SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:864:7)
I/flutter (13686): (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
I/flutter (13686): 
I/flutter (13686): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (13686): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (13686): The following assertion was thrown building PostsList(state: _PostsListState#09c9b):
I/flutter (13686): A RenderViewport expected a child of type RenderSliver but received a child of type RenderErrorBox.
I/flutter (13686): RenderObjects expect specific types of children because they coordinate with their children during
I/flutter (13686): layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a
I/flutter (13686): RenderSliver does not understand the RenderBox layout protocol.
I/flutter (13686): 
I/flutter (13686): The RenderViewport that expected a RenderSliver child was created by:
I/flutter (13686):   Viewport ← IgnorePointer-[GlobalKey#920d1] ← Semantics ← _PointerListener ← Listener ←
I/flutter (13686):   _GestureSemantics ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#8768b] ←
I/flutter (13686):   _PointerListener ← Listener ← _ScrollableScope ← _ScrollSemantics-[GlobalKey#10bbd] ←
I/flutter (13686):   RepaintBoundary ← ⋯
I/flutter (13686): 
I/flutter (13686): The RenderErrorBox that did not match the expected child type was created by:
I/flutter (13686):   ErrorWidget-[#a7044] ← RefreshIndicator ← PostsList ← Viewport ← IgnorePointer-[GlobalKey#920d1] ←
I/flutter (13686):   Semantics ← _PointerListener ← Listener ← _GestureSemantics ←
I/flutter (13686):   RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#8768b] ← _PointerListener ← Listener
I/flutter (13686):   ← ⋯
I/flutter (13686): 
I/flutter (13686): The relevant error-causing widget was:
I/flutter (13686):   PostsList file:///D:/Flutter/womenly/lib/screens/dashboard/dashboard_screen.dart:43:9
I/flutter (13686): 
I/flutter (13686): When the exception was thrown, this was the stack:
I/flutter (13686): #0      ContainerRenderObjectMixin.debugValidateChild.<anonymous closure> (package:flutter/src/rendering/object.dart:3123:9)
I/flutter (13686): #1      ContainerRenderObjectMixin.debugValidateChild (package:flutter/src/rendering/object.dart:3150:6)
I/flutter (13686): #2      MultiChildRenderObjectElement.insertRenderObjectChild (package:flutter/src/widgets/framework.dart:6191:25)
I/flutter (13686): #3      RenderObjectElement.attachRenderObject (package:flutter/src/widgets/framework.dart:5805:35)
I/flutter (13686): #4      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5501:5)
I/flutter (13686): ...     Normal element mounting (17 frames)
I/flutter (13686): #21     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #22     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): #23     _ViewportElement.mount (package:flutter/src/widgets/viewport.dart:225:11)
I/flutter (13686): ...     Normal element mounting (127 frames)
I/flutter (13686): #150    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #151    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (103 frames)
I/flutter (13686): #254    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #255    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (208 frames)
I/flutter (13686): #463    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #464    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (70 frames)
I/flutter (13686): #534    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #535    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (210 frames)
I/flutter (13686): #745    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #746    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (156 frames)
I/flutter (13686): #902    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #903    Element.updateChild (package:flutter/src/widgets/framework.dart:3324:20)
I/flutter (13686): #904    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4652:16)
I/flutter (13686): #905    StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
I/flutter (13686): #906    Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
I/flutter (13686): #907    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2730:33)
I/flutter (13686): #908    WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:913:20)
I/flutter (13686): #909    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
I/flutter (13686): #910    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
I/flutter (13686): #911    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
I/flutter (13686): #912    SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:864:7)
I/flutter (13686): (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
I/flutter (13686): 
I/flutter (13686): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (13686): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (13686): The following assertion was thrown building Listener:
I/flutter (13686): A RenderViewport expected a child of type RenderSliver but received a child of type RenderErrorBox.
I/flutter (13686): RenderObjects expect specific types of children because they coordinate with their children during
I/flutter (13686): layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a
I/flutter (13686): RenderSliver does not understand the RenderBox layout protocol.
I/flutter (13686): 
I/flutter (13686): The RenderViewport that expected a RenderSliver child was created by:
I/flutter (13686):   Viewport ← IgnorePointer-[GlobalKey#920d1] ← Semantics ← _PointerListener ← Listener ←
I/flutter (13686):   _GestureSemantics ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#8768b] ←
I/flutter (13686):   _PointerListener ← Listener ← _ScrollableScope ← _ScrollSemantics-[GlobalKey#10bbd] ←
I/flutter (13686):   RepaintBoundary ← ⋯
I/flutter (13686): 
I/flutter (13686): The RenderErrorBox that did not match the expected child type was created by:
I/flutter (13686):   ErrorWidget-[#e9942] ← PostsList ← Viewport ← IgnorePointer-[GlobalKey#920d1] ← Semantics ←
I/flutter (13686):   _PointerListener ← Listener ← _GestureSemantics ←
I/flutter (13686):   RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#8768b] ← _PointerListener ← Listener
I/flutter (13686):   ← _ScrollableScope ← ⋯
I/flutter (13686): 
I/flutter (13686): The relevant error-causing widget was:
I/flutter (13686):   CustomScrollView file:///D:/Flutter/womenly/lib/screens/dashboard/dashboard_screen.dart:10:14
I/flutter (13686): 
I/flutter (13686): When the exception was thrown, this was the stack:
I/flutter (13686): #0      ContainerRenderObjectMixin.debugValidateChild.<anonymous closure> (package:flutter/src/rendering/object.dart:3123:9)
I/flutter (13686): #1      ContainerRenderObjectMixin.debugValidateChild (package:flutter/src/rendering/object.dart:3150:6)
I/flutter (13686): #2      MultiChildRenderObjectElement.insertRenderObjectChild (package:flutter/src/widgets/framework.dart:6191:25)
I/flutter (13686): #3      RenderObjectElement.attachRenderObject (package:flutter/src/widgets/framework.dart:5805:35)
I/flutter (13686): #4      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5501:5)
I/flutter (13686): ...     Normal element mounting (9 frames)
I/flutter (13686): #13     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #14     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): #15     _ViewportElement.mount (package:flutter/src/widgets/viewport.dart:225:11)
I/flutter (13686): ...     Normal element mounting (127 frames)
I/flutter (13686): #142    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #143    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (103 frames)
I/flutter (13686): #246    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #247    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (208 frames)
I/flutter (13686): #455    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
I/flutter (13686): #456    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
I/flutter (13686): ...     Normal element mounting (70 frames)
EdsonBueno commented 3 years ago

Hi @Purus . The RefreshIndicator must be above the CustomScrollView, not above the PagedSliverList.

Purus commented 3 years ago

This might not work when the list component is created as a reusable widget across multiple screens. Please correct me if I am wrong.

EdsonBueno commented 3 years ago

If with "not work" you mean you can't have the RefreshIndicator inside the reusable widget, then yes! But only if you're using Slivers... Anyway, you already have to place your CustomScrollView outside of the reusable widget every time. Right?