wwwdata / implicitly_animated_reorderable_list

Fork of the discontinued plugin to continue maintaining it
MIT License
32 stars 22 forks source link

RangeError when item is deleted from list. #8

Closed Clashkid155 closed 1 year ago

Clashkid155 commented 2 years ago

Following my previous issue #6, this doesn't happen with ListView();

Home Page

class NewHome extends ConsumerWidget {
  const NewHome({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final pref = ref.watch(prefProvider);
    final checkBoxState = ref.watch(mainCheckBoxProvider);
    final newSt = ref.watch(fireHomeProvider);
    print("Ses La Rebuild");
    return newSt.when(
        data: (data) {
          final sti = data.docs;
          return ImplicitlyAnimatedList<QueryDocumentSnapshot<User>>(
              items: sti,
              itemBuilder: (context, animation, users, index) {
                final user = users.elementAt(index).data();
                final constructUser = user.copyToUser();
                final imageLink = appendUrl(pref,
                    pack: user.name,
                    currentUrl: user.tray);
                return UserTile(
                  key: ObjectKey(index)
                  image: imageLink
                  isChecked: checkBoxState,
                  time: user.lastUpdated.toDate(),
                  name: user.name),
                  edit: () {
                    print("OK");
                  },
                );
              },
              areItemsTheSame: (a, b) {
                return a.id == b.id;
              });
        },
        error: (error, e) {
          return Text("$error");
        },
        loading: () => const Center(child: CircularProgressIndicator()));

  }
}

StateNotifier


class HomeStreamNotifier
    extends StateNotifier<List<QueryDocumentSnapshot<User>>> {
  HomeStreamNotifier() : super([]);

  void remove(int index) {
    final newList = [...state];
    newList.removeAt(index);
    state = [...newList];
  }
}

If I run this same code with a ListView.builder, I won't get the RangeError Screenshot_1663272113

wwwdata commented 2 years ago

Hard to tell what goes wrong here without a stack trace. Can you copy that too? It should tell you in which file/line the range error happened. Then you can easily see if it was your code or somewhere else

Clashkid155 commented 2 years ago

I can't believe I didn't add the stack trace.

======== Exception caught by widgets library =======================================================
The following RangeError was thrown building:
RangeError (index): Invalid value: Not in inclusive range 0..2: 3

When the exception was thrown, this was the stack: 
#0      List.[] (dart:core-patch/growable_array.dart:264:36)
#1      List.elementAt (dart:core-patch/growable_array.dart:489:16)
#2      NewHome.build.<anonymous closure> (package:appMe/screens/new_home.dart:94:40)
#3      _SliverImplicitlyAnimatedListState.build.<anonymous closure> (package:animated_list_plus/src/implicitly_animated_list.dart:246:29)
#4      CustomSliverAnimatedListState._itemBuilder (package:animated_list_plus/src/custom_sliver_animated_list.dart:264:30)
#5      SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:471:22)
#6      SliverMultiBoxAdaptorElement._build (package:flutter/src/widgets/sliver.dart:1236:28)
#7      SliverMultiBoxAdaptorElement.performRebuild.processElement (package:flutter/src/widgets/sliver.dart:1169:67)
#8      Iterable.forEach (dart:core/iterable.dart:325:35)
#9      SliverMultiBoxAdaptorElement.performRebuild (package:flutter/src/widgets/sliver.dart:1213:24)
#10     SliverMultiBoxAdaptorElement.update (package:flutter/src/widgets/sliver.dart:1146:7)
#11     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#12     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#13     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#14     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#15     StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#16     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#17     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#18     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#19     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#20     StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#21     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#22     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#23     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#24     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5825:32)
#25     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6375:17)
#26     _ViewportElement.update (package:flutter/src/widgets/viewport.dart:237:11)
#27     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#28     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#29     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#30     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#31     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#32     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#33     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#34     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#35     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#36     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#37     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#38     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#39     StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#40     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#41     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#42     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#43     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#44     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#45     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#46     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#47     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#48     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#49     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#50     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#51     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#52     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#53     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#54     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#55     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#56     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#57     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#58     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#59     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#60     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#61     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#62     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#63     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#64     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#65     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#66     StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#67     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#68     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#69     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#70     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#71     StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#72     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#73     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#74     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#75     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#76     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#77     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#78     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#79     StatelessElement.update (package:flutter/src/widgets/framework.dart:4883:5)
#80     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#81     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#82     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#83     StatelessElement.update (package:flutter/src/widgets/framework.dart:4883:5)
#84     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#85     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#86     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#87     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#88     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#89     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:891:21)
#90     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#91     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#92     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#93     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997:5)
#97     _invoke (dart:ui/hooks.dart:151:10)
#98     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#99     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
====================================================================================================

Line 94 of newHome is: final user = users.elementAt(index).data(); Everything works perfectly with the exact code on a ListView.builder, changing the value of removeDuration: const Duration(), affects how long the error will show too,

redarflap commented 2 years ago

Same issue here. I have a checkbox which allows to filter my list. When i click it, the widget is rebuilt with a filtered list of items. It doesn't matter how many items are removed or if the item is removed from the end or the middle of the list.

I am also using a StateNotifierProvider from Riverpod and fetching my itemList using watch(). But i doubt that would cause the issue?

ImplicitlyAnimatedList(
  shrinkWrap: true,
  physics: const NeverScrollableScrollPhysics(),
  items: taskState.items,
  itemBuilder: (context, animation, item, i) =>
      SizeFadeTransition(
    sizeFraction: 0.7,
    curve: Curves.easeInOut,
    animation: animation,
    child: Card(
      child: TaskTile(
        item: taskState.items[i],
        projectId: projectId,
      ),
    ),
  ),
  areItemsTheSame: (oldItem, newItem) =>
      oldItem.task.id == newItem.task.id,
wwwdata commented 2 years ago

Ok, so whenever the list adds/removes multiple items at the same time you get crashes. I will try to reproduce this with a small example app and then fix it :)

wwwdata commented 2 years ago

Also cannot reproduce this... Can you please provide an example? You also did re-render the widget after you modified the list (called setState?)? So Flutter updates and is not trying to access items in the list that might already have been deleted? Because this could also be the problem when you just change the underlying list and the list builder then still tries to access that item.

But: Please try to re-produce the problem and paste the code here so that I have something that I can crash the lib with and then fix it :)

Shams-Mahmoud commented 1 year ago

same here

redarflap commented 1 year ago

Also cannot reproduce this... Can you please provide an example? You also did re-render the widget after you modified the list (called setState?)? So Flutter updates and is not trying to access items in the list that might already have been deleted? Because this could also be the problem when you just change the underlying list and the list builder then still tries to access that item.

But: Please try to re-produce the problem and paste the code here so that I have something that I can crash the lib with and then fix it :)

Sorry for the late reply. I also tried to re-produce it in a minimal example (updating via riverpod state change), but i wasn't able to do so. I'm not sure where the difference is.

Update: After i copied my working minimal example over to my app, it seems to work now. I can't figure out any relevant difference to my old try back then. But i also upgraded Flutter to 3.7.0 in the meantime (and this package to 0.4.5). So maybe it was a flutter-related problem after all.

githubdoandre commented 1 year ago

@Clashkid155

I solved this using 'item' from itemBuilder instead of index direct from my data

Before

 SliverImplicitlyAnimatedList<Ticket>(
      items: _controller.ticketController.filteredData,
      areItemsTheSame: (oldItem, newItem) => oldItem.id == newItem.id,
      itemBuilder: (_, itemAnimation, item, index) => myWidget(child: _controller.ticketController.filteredData[index].id

After

 SliverImplicitlyAnimatedList<Ticket>(
      items: _controller.ticketController.filteredData,
      areItemsTheSame: (oldItem, newItem) => oldItem.id == newItem.id,
      itemBuilder: (_, itemAnimation, item, index) => myWidget(child: item.id..
oleksiiparf commented 1 year ago

@githubdoandre

I solved this using 'item' from itemBuilder instead of index direct from my data

Didn't even pay attention that itemBuilder function has an 'item' parameter, that really works!

Clashkid155 commented 1 year ago

@githubdoandre My app is no longer functional so I can't test this.

I'll be closing this now.