【问题标题】:flutter dropdown Failes when class is used as value instead of String当类用作值而不是字符串时,颤动下拉失败
【发布时间】:2019-12-11 03:46:47
【问题描述】:

我有以下代码。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'My App',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: SimpleScreen());
  }
}

class SimpleScreen extends StatefulWidget {
  @override
  _SimpleScreenState createState() => _SimpleScreenState();
}

class _SimpleScreenState extends State<SimpleScreen> {
  ItemCls currentValue = ItemCls(name: 'one', price: 1);

  List<DropdownMenuItem> _menuItems = <DropdownMenuItem>[
    DropdownMenuItem(
        child: new Container(
          child: new Text("Item#1"),
          width: 200.0,
        ),
        value: ItemCls(name: 'one', price: 1)),
    DropdownMenuItem(
        child: new Container(
          child: new Text("Item#2"),
          width: 200.0,
        ),
        value: ItemCls(name: 'two', price: 2))
  ];

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: Center(
      child: DropdownButton(
        value: currentValue,
        items: _menuItems,
        onChanged: onChanged,
        style: Theme.of(context).textTheme.title,
      ),
    ));
  }

  void onChanged(value) {
    setState(() {
      currentValue = value;
    });
   // print(value);
  }
}

class ItemCls {
  final String name;
  final double price;

  const ItemCls({
    @required this.name,
    @required this.price,
  })  : assert(name != null),
        assert(price != null);
}

失败了

在构建 SimpleScreen(dirty, 依赖项:[_LocalizationsScope-[GlobalKey#b1ff3], _InheritedTheme],状态:_SimpleScreenState#d473f):'package:flutter/src/material/dropdown.dart':断言失败:行 620 位置 15: '项目 == 空 ||项目.isEmpty ||值 == 空 || items.where((DropdownMenuItem item) => item.value == value).length == 1':不正确。

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    每个DropDownMenuItem 中的value 必须是唯一的。 Dart 通过两种方式确保唯一性:定义 == 运算符和在对象上调用 hashCode。您需要将两者都添加到 ItemCls 类中:

    class ItemCls {
      final String name;
      final double price;
    
      const ItemCls({
        @required this.name,
        @required this.price,
      })  : assert(name != null),
            assert(price != null);
    
      bool operator ==(dynamic other) {
        return other is ItemCls && 
               this.name == other.name && 
               this.price == other.price;
      }
    
      @override
      int get hashCode {
        // Hash code algorithm derived from https://www.sitepoint.com/how-to-implement-javas-hashcode-correctly/
        int hashCode = 1;
        hashCode = (23 * hashCode) + this.name.hashCode;
        hashCode = (23 * hashCode) + this.price.hashCode;
        return hashCode;
      }
    }
    

    【讨论】:

      【解决方案2】:

      原因
      实例 ItemCls currentValue = ItemCls(name: 'one', price: 1); 不等于 value: ItemCls(name: 'one', price: 1)),
      他们有不同的地址并被视为不同的价值
      所以 DropdownButton 认为默认值 ItemCls(name: 'one', price: 1) 在选择列表中不存在

      解决方案
      使用List&lt;ItemCls&gt; 包含您的选择并将currentValue 指向列表的第一个值

      ItemCls currentValue;
        static List<ItemCls> itemList = [
          ItemCls(name: 'one', price: 1),
          ItemCls(name: 'two', price: 2)
        ];
        ...
       DropdownMenuItem<ItemCls>(
          child: new Container(
            child: new Text("Item#1"),
            width: 200.0,
          ),
          value: itemList[0]),
      ...
      void initState() {
      // TODO: implement initState
      currentValue = itemList[0];
      }
      

      工作演示

      完整代码

      import 'package:flutter/material.dart';
      
      void main() => runApp(MyApp());
      
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
              title: 'My App',
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              home: SimpleScreen());
        }
      }
      
      class SimpleScreen extends StatefulWidget {
        @override
        _SimpleScreenState createState() => _SimpleScreenState();
      }
      
      class _SimpleScreenState extends State<SimpleScreen> {
        ItemCls currentValue;
        static List<ItemCls> itemList = [
          ItemCls(name: 'one', price: 1),
          ItemCls(name: 'two', price: 2)
        ];
      
        List<DropdownMenuItem<ItemCls>> _menuItems = <DropdownMenuItem<ItemCls>>[
          DropdownMenuItem<ItemCls>(
              child: new Container(
                child: new Text("Item#1"),
                width: 200.0,
              ),
              value: itemList[0]),
          DropdownMenuItem<ItemCls>(
              child: new Container(
                child: new Text("Item#2"),
                width: 200.0,
              ),
              value: itemList[1])
        ];
      
        @override
        void initState() {
          // TODO: implement initState
          currentValue = itemList[0];
        }
      
        @override
        Widget build(BuildContext context) {
          return new Scaffold(
              body: Center(
            child: DropdownButton<ItemCls>(
              value: currentValue,
              items: _menuItems,
              onChanged: onChanged,
              style: Theme.of(context).textTheme.title,
            ),
          ));
        }
      
        void onChanged(value) {
          setState(() {
            currentValue = value;
          });
          // print(value);
        }
      }
      
      class ItemCls {
        final String name;
        final double price;
      
        const ItemCls({
          @required this.name,
          @required this.price,
        })  : assert(name != null),
              assert(price != null);
      }
      

      【讨论】:

        猜你喜欢
        • 2018-11-23
        • 2019-06-08
        • 2018-10-26
        • 1970-01-01
        • 1970-01-01
        • 2021-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多