Dismissible confirmDismiss in combination with new route navigation causes Flutter crash

二次信任 提交于 2020-01-13 20:27:54

问题


The context:
I stumbled upon a minor crash while testing a ListView of Dismissibles in Flutter. When swiping a dismissible, a Dialog is shown using the confirmDismiss option, for confirmation. This all works well, however the UI crashes when testing an unlikely use case. On the page are several options to navigate to other (named) routes. When a dismissible is swiped, and during the animation an option to navigate to a new route is tapped, the crash happens.

How to replicate the crash:

  1. Dismiss the Dismissible
  2. During the animation that follows (the translation of the position of the dismissible), tap on an action that brings you to a new route. The timeframe to do this is minimal, I've extended it in the example.
  3. The new route loads and the UI freezes

For reference, this is the error message:

AnimationController.reverse() called after AnimationController.dispose()

The culprit is the animation that tries to reverse when it was already disposed:

package:flutter/…/widgets/dismissible.dart:449

Things I've tried:
Initially, I tried checking this.mounted inside the showDialog builder but quickly realised the problem is not situated there.
Another idea was to circumvent the problem by using CancelableOperation.fromFuture and then cancelling it in the dispose() method of the encompassing widget, but that was to no avail.

What can I do solve or at least circumvent this issue?

The code (can also be found and cloned here):

// (...)
class _DimissibleListState extends State<DimissibleList> {
  int childSize = 3;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: childSize,
        itemBuilder: (context, index) {
          if (index == 0) {
            return _buildNextPageAction(context);
          }
          return _buildDismissible();
        },
      ),
    );
  }

  Widget _buildNextPageAction(context) {
    return FlatButton(
      child: Text("Go to a new page"),
      onPressed: () => Navigator.of(context).pushNamed('/other'),
    );
  }

  Dismissible _buildDismissible() {
    GlobalKey key = GlobalKey();

    return Dismissible(
      key: key,
      child: ListTile(
        title: Container(
          padding: const EdgeInsets.all(8.0),
          color: Colors.red,
          child: Text("A dismissible. Nice."),
        ),
      ),
      confirmDismiss: (direction) async {
        await Future.delayed(const Duration(milliseconds: 100), () {});
        return showDialog(
          context: context,
          builder: (context) {
            return Dialog(
              child: FlatButton(
                onPressed: () => Navigator.of(context).pop(true),
                child: Text("Confirm dismiss?"),
              ),
            );
          },
        );
      },
      resizeDuration: null,
      onDismissed: (direction) => setState(() => childSize--),
    );
  }
}

回答1:


I had almost same problem with confirmDismiss ,in my case I was using (await Navigator.push() ) inside of confirmDismiss to navigate to another screen but in return I faced this error :

AnimationController.reverse() called after AnimationController.dispose()

so to solve my problem inside of confirmDismiss I call a future function out side of confirmDismiss (without await ) and then add return true or false after that function call to finish animation of confirmDismiss.



来源:https://stackoverflow.com/questions/56166236/dismissible-confirmdismiss-in-combination-with-new-route-navigation-causes-flutt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!