可忽略的确认与新路线导航结合使用时可导致Flutter崩溃 [英] Dismissible confirmDismiss in combination with new route navigation causes Flutter crash

查看:112
本文介绍了可忽略的确认与新路线导航结合使用时可导致Flutter崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文:

我在测试 ListView 时偶然发现了一次轻微崩溃在Flutter中> dismissible 。刷下可解雇对象时,将使用 confirmDismiss 选项显示对话框,以进行确认。这一切都很好,但是在测试不太可能的用例时,UI会崩溃。页面上有几个导航到其他(命名)路线的选项。刷下可解雇人员时,在动画过程中,点击了导航到新路线的选项,就会发生崩溃。



如何复制崩溃:


  1. 关闭可忽略项

  2. 在随后的动画中(平移可解雇人员的位置),点击将您带到
    新路线的操作。做到这一点的时间是最小的,在示例中已对其进行了扩展。

  3. 新路线加载且UI冻结

作为参考,这是错误消息:


AnimationController.reverse()是在AnimationController.dispose之后调用的()


罪魁祸首是试图在已经处理掉的动画上反转:


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


我要注意的事情ve尝试过:

最初,我尝试在 showDialog构建器 this.mount $ c>,但很快就意识到问题不在那儿。

另一个想法是通过使用 CancelableOperation.fromFuture 来解决问题在包含的小部件的 dispose()方法中添加它,但这无济于事。



有什么可以我确实解决或至少规避了此问题?



代码(也可以找到并克隆此处):

  // (...)
类_DimissibleListState扩展了State< DimissibleList> {
int childSize = 3;

@override
构件构建(BuildContext上下文){
return Scaffold(
body:ListView.builder(
itemCount:childSize,
itemBuilder :(上下文,索引){
if(index == 0){
return _buildNextPageAction(context);
}
return _buildDismissible();
},
),
);
}

小部件_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,
child:ListTile(
title:Container(
padding:const EdgeInsets.all(8.0),
颜色:Colors.red,
孩子:Text( A dismissible。Nice。),
),
),
ConfirmDismiss :(方向)异步{ b $ b等待Future.delayed(const Duration(毫秒:100),(){});
return showDialog(
context:context,
builder:(context){
return Dialog(
child:FlatButton(
onPressed:()=> Navigator.of(context).pop(true),
child:Text(确认关闭吗?),
),
);
},
);
},
resizeDuration:null,
onDismissed:(direction)=> setState(()=> childSize--),
);
}
}


解决方案

I发生了与ConfirmDismiss几乎相同的问题,就我而言,我在confirmDismiss内部使用(await Navigator.push())导航到另一个屏幕,但作为回报,我遇到了此错误:在
AnimationController.dispose()之后调用blockquote>

AnimationController.reverse()


解决我的问题时,我在confirmDismiss内调用了一个外部函数,但未添加await,然后在该函数调用后添加return true或false来完成ConfirmDismiss的动画。


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--),
    );
  }
}

解决方案

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.

这篇关于可忽略的确认与新路线导航结合使用时可导致Flutter崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆