Flutter-将动态项目作为键传递 [英] Flutter - Pass a dynamic Item as Key

查看:54
本文介绍了Flutter-将动态项目作为键传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在 flutter run 调试模式下运行时,以下代码显示以下错误:

The code below is displaying the following error when I run in flutter run debug mode:

类型列表"不是值"的字符串"类型的子类型,其中

当我在发布模式下运行 flutter run --release 时,该错误不会出现,并且我可以识别出我选择删除的项目.

When I run in release mode flutter run --release the error does not appear and I can identify the item I selected to delete.

问题在第39行: key:新的Key(i)

仅接受字符串作为值:键(字符串值)→键

The key only accepts string as value: Key(String value) → Key

但是我要传递一个看来是动态项目的 List :动态i

But I'm passing a List that appears to be a dynamic item: dynamic i

但是我需要在 Key 上传递一个 List ,以便能够识别被排除的物品.

But I need to pass a List on the Key to be able to identify what the excluded item will be.

如何在调试模式下解决此问题?

How could I solve this problem in debug mode?

为什么会发生这种现象,而在发布模式下却没有出现此问题?

And why is this behavior happening and in the release mode the problem does not occur?

import 'package:flutter/material.dart';
import 'dart:ui' as ui;

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> tiles;
  List foos = [];

  @override
  void initState() {
    this.foos = [[0, 'foo1'], [1, 'foo2'], [2, 'foo3'], [3, 'foo4']];
    this.tiles = buildTile(this.foos);
    super.initState();
  }

  //function
  List<Widget> buildTile(List list) {
    var x = [];
    for(var i in list) {
      x.add(
        new ItemCategory(
          key: new Key(i),
          category: i[1],
          onPressed: () {
            setState(() {
              list.removeAt(i[0]);
              var list2 = [];
              for(var x = 0; x < list.length; x++) {
                list2.add([ x, list[x][1] ]);
              }
              this.tiles = buildTile(list2);
            });
          },
        )
      );
    }
    return x;
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Categories'),
      ),
      body: new ListView(
        padding: new EdgeInsets.only(top: 8.0, right: 0.0, left: 0.0),
        children: this.tiles
      )
    );
  }
}

class ItemCategory extends StatefulWidget {
  ItemCategory({ Key key, this.category, this.onPressed}) : super(key: key);

  final String category;
  final VoidCallback onPressed;

  @override
  ItemCategoryState createState() => new ItemCategoryState();
}

class ItemCategoryState extends State<ItemCategory> with TickerProviderStateMixin {
  ItemCategoryState();

  AnimationController _controller;
  Animation<double> _animation;
  double flingOpening;
  bool startFling = true;

  void initState() {
    super.initState();
    _controller = new AnimationController(duration: 
      const Duration(milliseconds: 246), vsync: this);

    _animation = new CurvedAnimation(
      parent: _controller,
      curve: new Interval(0.0, 1.0, curve: Curves.linear),
    );
  }

  void _move(DragUpdateDetails details) {
    final double delta = details.primaryDelta / 304;
    _controller.value -= delta;
  }

  void _settle(DragEndDetails details) {
    if(this.startFling) {
      _controller.fling(velocity: 1.0);
      this.startFling = false;
    } else if(!this.startFling){
      _controller.fling(velocity: -1.0);
      this.startFling = true;
    }
  }

  @override
  Widget build(BuildContext context) {
    final ui.Size logicalSize = MediaQuery.of(context).size;
    final double _width = logicalSize.width;
    this.flingOpening = -(48.0/_width);

    return new GestureDetector(
      onHorizontalDragUpdate: _move,
      onHorizontalDragEnd: _settle,
      child: new Stack(
        children: <Widget>[
          new Positioned.fill(
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                new Container(
                  decoration: new BoxDecoration(
                    color: new Color(0xFFE57373),
                  ),
                  child: new IconButton(
                    icon: new Icon(Icons.delete),
                    color: new Color(0xFFFFFFFF),
                    onPressed: widget.onPressed
                  )
                ),
              ],
            ),
          ),
          new SlideTransition(
            position: new Tween<Offset>(
              begin:  Offset.zero,
              end: new Offset(this.flingOpening, 0.0),
            ).animate(_animation),
            child: new Container(
              decoration: new BoxDecoration(
                border: new Border(
                  top: new BorderSide(style: BorderStyle.solid, color: Colors.black26),
                ),
                color: new Color(0xFFFFFFFF),
              ),
              margin: new EdgeInsets.only(top: 0.0, bottom: 0.0),
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  new Expanded(
                    child: new Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        new Container(
                          margin: new EdgeInsets.only(left: 16.0),
                          padding: new EdgeInsets.only(right: 40.0, top: 4.5, bottom: 4.5),
                          child: new Row(
                            children: <Widget>[
                              new Container(
                                margin: new EdgeInsets.only(right: 16.0),
                                child: new Icon(
                                  Icons.brightness_1,
                                  color: Colors.black,
                                  size: 35.0,
                                ),
                              ),
                              new Text(widget.category),
                            ],
                          )
                        )
                      ],
                    ),
                  )
                ],
              ),
            )
          ),
        ],
      )
    );
  }
}

推荐答案

您应该知道-release 标志会删除所有 assert 并从应用程序中进行类型检查.这就是为什么您的错误消失的原因.断言/类型检查在这里仅用作更好的开发工具,无需实际运行应用程序即可查看潜在错误.发行版本不需要知道这些.

You should know that --release flag remove all assert and type checking from the app. Which is why your error disappear. Asserts/Type Check are here only as tools for a better development to see potential errors without having to actually run the app. A release build don't need to be aware of these.

在您的情况下,出现问题是因为您没有在 List< Widget>中指定 list 的通用"类型.buildTile(列表列表);默认将 list 设置为 List< dynamic> .因此,编译器不知道列表中的元素是什么类型,因此允许您执行 new Key(i).因为 i 可能 String .

In your case, the problem occurs because you haven't specified the 'generic' type of list in List<Widget> buildTile(List list) ; which default list to List<dynamic>. Consequence, the compiler don't know what type is an element of your list and therefore allows you to do new Key(i). Because i may be a String.

将函数原型修改为 List< Widget>buildTile(List< List< String>>列表)(此处为列表的 real 类型)将允许编译器向您发出潜在错误的警报.该错误是 List< String>不能被分配为在新键(i)上键入String .

Modifying your function prototype to List<Widget> buildTile(List<List<String>> list) (which is the real type of your list here) will allow the compiler to alert you from a potential error. And that error is List<String> can't be assigned to type String on new Key(i).

要解决该错误,您可以改为执行 new Key(i.toString()),该键将序列化您的列表(由于是原始对象).

To fix that error, you can instead do new Key(i.toString(), which will serialize your list (thanks to being primitive objects).

或使用从Key继承的 ObjectKey ,但不是使用 String 作为参数,而是采用了 Object ,例如键:新的ObjectKey(i)

Or use the ObjectKey that inherit from Key, but instead of using String as parameter, it takes anObject such as key: new ObjectKey(i)

这篇关于Flutter-将动态项目作为键传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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