颤振 - 将动态项目作为键传递

时间:2017-12-05 00:17:10

标签: dart flutter

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

type 'List' is not a subtype of type 'String' of 'value' where

enter image description here

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

enter image description here

问题在第39行: key: new Key(i),

key只接受字符串作为值: Key(String value) → Key

但我传递的List似乎是一个动态项目: dynamic i

但我需要在List上传递Key,以便能够识别被排除的项目。

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

为什么会出现这种情况并且在发布模式下问题不会发生?

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

1 个答案:

答案 0 :(得分:3)

您应该知道--release标志会删除所有assert并从应用中键入检查。这就是你的错误消失的原因。 断言/类型检查仅作为更好的开发工具,以便在不必实际运行应用程序的情况下查看潜在错误。发布版本不需要了解这些。

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

将函数原型修改为List<Widget> buildTile(List<List<String>> list)(此处列表的真实类型)将允许编译器提醒您潜在的错误。 List<String> can't be assigned to type String上的错误为new Key(i)

要修复该错误,您可以执行new Key(i.toString(),这将序列化您的列表(感谢原始对象)。

或者使用从Key继承的ObjectKey,但不是使用String作为参数,而是需要Object,例如key: new ObjectKey(i)