philip-brink/DragAndDropLists

Item drag crashes only on web

jacobokoenig opened this issue · 10 comments

Hi,

I've implemented a list of lists which drags and drops effectively on mobile and tablet, but on web causes a weird and unusual crash. Here's the log of it:

"Error: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
    at Object.throw_ [as throw] (http://localhost:59286/dart_sdk.js:4339:11)
    at http://localhost:59286/packages/flutter/src/widgets/widget_span.dart.lib.js:13881:23
    at ink_well._InkResponseState.new.get context [as context] (http://localhost:59286/packages/flutter/src/widgets/widget_span.dart.lib.js:13884:25)
    at ink_well._InkResponseState.new.updateHighlight (http://localhost:59286/packages/flutter/src/material/icon_button.dart.lib.js:50532:68)
    at ink_well._InkResponseState.new.[_handleHoverChange] (http://localhost:59286/packages/flutter/src/material/icon_button.dart.lib.js:50748:12)
    at ink_well._InkResponseState.new.[_handleMouseEnter] (http://localhost:59286/packages/flutter/src/material/icon_button.dart.lib.js:50739:33)
    at Function._handleDeviceUpdateMouseEvents (http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:5765:75)
    at mouse_tracking.MouseTracker.new.handleDeviceUpdate (http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:5773:46)
    at http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:5045:16
    at mouse_tracking.MouseTracker.new.[_deviceUpdatePhase] (http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:4979:7)
    at http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:5032:33
    at mouse_tracking.MouseTracker.new.[_monitorMouseConnection] (http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:4969:7)
    at mouse_tracking.MouseTracker.new.updateWithEvent (http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:5031:36)
    at binding$5.WidgetsFlutterBinding.new.dispatchEvent (http://localhost:59286/packages/flutter/src/rendering/layer.dart.lib.js:5967:45)
    at binding$5.WidgetsFlutterBinding.new.[_handlePointerEventImmediately] (http://localhost:59286/packages/flutter/src/gestures/binding.dart.lib.js:260:14)
    at binding$5.WidgetsFlutterBinding.new.handlePointerEvent (http://localhost:59286/packages/flutter/src/gestures/binding.dart.lib.js:233:43)
    at binding$5.WidgetsFlutterBinding.new.[_flushPointerEventQueue] (http://localhost:59286/packages/flutter/src/gestures/binding.dart.lib.js:222:14)
    at binding$5.WidgetsFlutterBinding.new.[_handlePointerDataPacket] (http://localhost:59286/packages/flutter/src/gestures/binding.dart.lib.js:212:65)
    at Object._invoke1 (http://localhost:59286/dart_sdk.js:176547:7)
    at _engine.EngineWindow.new.invokeOnPointerDataPacket (http://localhost:59286/dart_sdk.js:172276:15)
    at _engine.PointerBinding.__.[_onPointerData] (http://localhost:59286/dart_sdk.js:159053:24)
    at http://localhost:59286/dart_sdk.js:159429:26
    at http://localhost:59286/dart_sdk.js:159401:16
    at http://localhost:59286/dart_sdk.js:159154:11"

And this is the list implementation:

return state is MenuLoaded
            ? DragAndDropLists(
                scrollController: controller,
                onItemReorder: context.bloc<MenuCubit>().reorderItems,
                onListReorder: context.bloc<MenuCubit>().reorderCategories,
                listDragOnLongPress: false,
                itemDragOnLongPress: false,
                children: state.categories.map((category) {
                  return DragAndDropList(
                    header: CategoryTitle(
                      category: category,
                    ),
                    children: category.items
                        .map(
                          (item) => DragAndDropItem(
                            child: Padding(
                              padding: const EdgeInsets.only(top: 12),
                              child: MenuItemTile(item: item),
                            ),
                          ),
                        )
                        .toList(),
                    footer: Container(
                      padding: const EdgeInsets.only(bottom: Spacing.standardSpacing),
                      alignment: Alignment.centerRight,
                      child: GestureDetector(
                        onTap: () async {
                          await push(
                            context,
                            ProductDetailView(
                              item: MenuItem.empty(
                                locationId: category.locationId,
                                categoryId: category.id,
                                order: category.items?.length ?? 0,
                              ),
                            ),
                          );
                          context.bloc<MenuCubit>().refresh();
                        },
                        child: Text(
                          '+ Add Product',
                          style: Theme.of(context).textTheme.bodyText2,
                          textAlign: TextAlign.center,
                        ),
                      ),
                    ),
                  );
                }).toList(),
              )
            : Container();

Given all of the widgets surrounding the list are Stateless, it's even weirder. Any clues as to why this might be?

Hi @jacobokoenig, I wonder if this might be related to #10. Could you try commenting out the onTap method in your GestureDetector to see if it still throws this exception? Does the exception happen on loading the widget or on starting to drag?

Hi @philip-brink, seemingly unrelated as I removed the GestureDetector altogether but the problem remains the same. The exception happens on starting to drag.

@philip-brink any ideas on this subject? I appreciate any guidance you can give me.

I've tried reproducing it but without any luck. What's your flutter doctor -v output?

Are the widgets inside the list (CategoryTitle, ProductDetailView) stateless as well?

Just to try to eliminate all potential issues, I've also added mounted checks to all the setState methods in the package in v 0.2.6 which you can try to see if it solves the problem.

Thanks for your help @philip-brink.

CategoryTitle, ProductDetailView are indeed Stateless as well. I've upgraded but no difference in the error. Here's my flutter doctor:

[✓] Flutter (Channel dev, 1.24.0-1.0.pre, on Mac OS X 10.15.7 19H2 darwin-x64, locale en-GB)
• Flutter version 1.24.0-1.0.pre at /Users/jacobokoenig/Developer/flutter
• Framework revision 12bea61c29 (7 days ago), 2020-10-14 15:57:04 -0700
• Engine revision 069b3cf8f0
• Dart version 2.11.0 (build 2.11.0-218.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/jacobokoenig/Library/Android/sdk
• Platform android-29, build-tools 29.0.2
• ANDROID_HOME = /Users/jacobokoenig/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 12.1, Build version 12A7403
• CocoaPods version 1.10.0.rc.1

[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 42.1.1
• Dart plugin version 191.8593
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.50.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.15.1

[✓] Connected device (3 available)
• Banana Pancakes (mobile) • 00008030-001915603E10802E • ios • iOS 14.0.1
• Web Server (web) • web-server • web-javascript • Flutter Tools
• Chrome (web) • chrome • web-javascript • Google Chrome 86.0.4240.111
! Error: Banana Pancakes is busy: Copying cache files from device. Xcode will continue when Banana Pancakes is
finished. (code -10)

• No issues found!

@philip-brink I found the issue. Inside of the tile itself, there was an InkWell with an onTap that navigates towards another view, hence dismounting the lists and causing the error. As it turns out changing the InkWell to a GestureDetector fixed the issue. Something different goes between them on the web where [I suppose] the InkWell calls onTap during the drag whilst GestureDetector doesn't.

Thank you so much for your help.

@jacobokoenig Great! That's good to know. Until this issue with dragging on flutter web gets resolved I'll add some info in the readme as a known problem. Thanks!

@jacobokoenig This issue seems to be solved now on the flutter dev channel.

Just faced the same issue, for all searching in their code for a solution: ListTile and therefore ExpansionTile is using InkWell - so it doesn't work with those widgets as well.

Is it still the case? I'm considering using the package and ListTile is a standard component to use in a list so that would be no go to use the package.