【问题标题】:Dismissible confirmDismiss in combination with new route navigation causes Flutter crashDismissible confirmDismiss 结合新的路由导航导致 Flutter 崩溃
【发布时间】:2019-10-03 14:16:51
【问题描述】:

上下文:
我在 Flutter 中测试Dismissibles 中的ListView 时偶然发现了一次小崩溃。滑动可关闭项时,使用confirmDismiss 选项显示Dialog 以进行确认。这一切都很好,但是在测试不太可能的用例时 UI 会崩溃。页面上有几个选项可以导航到其他(命名的)路线。当轻扫可关闭的对象时,并且在动画期间点击导航到新路线的选项时,会发生崩溃。

如何复制崩溃:

  1. 解雇被解雇的人
  2. 在随后的动画(可关闭位置的平移)中,点击一个动作,将您带到 新路线。执行此操作的时间范围很短,我在示例中对其进行了扩展。
  3. 新路由加载,UI 冻结

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

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

罪魁祸首是动画在它已经被释放时试图反转:

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

我尝试过的事情:
最初,我尝试在showDialog builder 中检查this.mounted,但很快意识到问题不在于那里。
另一个想法是通过使用CancelableOperation.fromFuture 来规避问题,然后在包含小部件的dispose() 方法中取消它,但这无济于事。

我能做些什么来解决或至少规避这个问题?

代码(也可以找到克隆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--),
    );
  }
}

【问题讨论】:

  • 您是否尝试过延迟导航?就像 500 毫秒后弹出一样?
  • 嘿@danypata,这是一个有趣的思路!但是延迟并没有解决问题。现在当用户返回到带有列表视图的页面时应用程序崩溃(并且错误保持不变)
  • 我添加了一行“await Future.delayed(const Duration(milliseconds: 100), () {});”,它对我有用。感谢您提出这个问题。

标签: dart flutter future dismissible


【解决方案1】:

confirmDismiss 遇到了几乎相同的问题,在我的情况下,我在 confirmDismiss 中使用 (await Navigator.push()) 导航到另一个屏幕,但作为回报,我遇到了这个错误:

AnimationController.reverse() 之后调用 AnimationController.dispose()

所以为了解决我在 confirmDismiss 内部的问题,我在 confirmDismiss 之外调用了一个未来函数(没有 await ),然后在该函数调用之后添加 return true 或 false 以完成 confirmDismiss 的动画。

【讨论】:

    猜你喜欢
    • 2019-09-10
    • 2021-10-07
    • 2022-01-21
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 2012-02-01
    相关资源
    最近更新 更多