Flutter下拉框绑定数据库值时遇空安全调用错误求助
错误出现在以下代码行:
items: machineList[index].serienummer((String items)
收到的错误提示:
The function can't be unconditionally invoked because it can be null.
尝试过添加!、?、??等空安全操作符,问题仍未解决。
页面Dart代码
class _MachinepageState extends State<Machinepage> { _MachinepageState(); final ApiService api = ApiService(); late List<Machine> machineList; String dropdownvalue = ""; @override initState(){ super.initState(); _getMachine(); machineList = []; } void _getMachine() async{ machineList = (await ApiService().getMoreMachine(widget.klant.klantId.toString())); Future.delayed(const Duration(seconds: 1)).then((value) => setState(() {})); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar(title: const Text('Menu'), backgroundColor:Colors.deepOrange ), body: machineList == null || machineList.isEmpty ? const Center( child: CircularProgressIndicator(), ) : SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget> [ ListView.builder( shrinkWrap: true, itemCount: machineList == null? 0 : machineList.length, itemBuilder: (BuildContext context, int index) => Row( children: [ Container( margin: const EdgeInsets.only(top: 20.0, bottom: 25.0), child: DropdownButton( // Initial Value value: machineList[1].serienummer, // Down Arrow Icon icon: const Icon(Icons.keyboard_arrow_down), // Array list of items items: machineList[index].serienummer((String items) { return DropdownMenuItem( value: items, child: Text(items), ); }).toList(), // After selecting the desired option, it will // change button value to selected value onChanged: (String? newValue) { setState(() { dropdownvalue = newValue!; }); }, ), ) ], ) ),
Machine模型代码
import 'dart:convert'; import 'package:flutter/src/material/dropdown.dart'; List<Machine> welcomeFromJson(String str) => List<Machine>.from(json.decode(str).map((x) => Machine.fromJson(x))); String welcomeToJson(List<Machine> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson()))); class Machine { Machine({ this.serienummerId, this.serienummer, this.bouwjaar, this.urenstand, this.locatie, this.klantId, }); int? serienummerId; String? serienummer; String? bouwjaar; String? urenstand; String? locatie; String? klantId; factory Machine.fromJson(Map<String, dynamic> json) => Machine( serienummerId: json["SerienummerId"], serienummer: json["Serienummer"], bouwjaar: json["Bouwjaar"], urenstand: json["Urenstand"], locatie: json["Locatie"], klantId: json["KlantId"], ); Map<String, dynamic> toJson() => { "SerienummerId": serienummerId, "Serienummer": serienummer, "Bouwjaar": bouwjaar, "Urenstand": urenstand, "Locatie": locatie, "KlantId": klantId, }; }
解决方案
核心问题是对DropdownButton的items属性用法理解错误:
machineList[index].serienummer是单个String?字段,不是列表,不能直接用来生成下拉选项,需要遍历整个machineList提取所有有效serienummer值。- 必须处理空安全,过滤掉
serienummer为null的项。
修改后的DropdownButton代码:
DropdownButton<String>( // 初始化值确保存在于选项列表中,避免报错 value: dropdownvalue.isNotEmpty ? dropdownvalue : machineList.firstWhere((m) => m.serienummer != null).serienummer!, icon: const Icon(Icons.keyboard_arrow_down), // 遍历列表生成下拉项,过滤空值 items: machineList .where((machine) => machine.serienummer != null) .map((machine) { return DropdownMenuItem<String>( value: machine.serienummer!, child: Text(machine.serienummer!), ); }).toList(), onChanged: (String? newValue) { setState(() { dropdownvalue = newValue!; }); }, )
附带优化点:
- 移除
initState中多余的machineList = [];,因为已经用late声明,直接在_getMachine中赋值即可。 - 简化
_getMachine的setState调用,去掉不必要的延迟:
void _getMachine() async{ machineList = await ApiService().getMoreMachine(widget.klant.klantId.toString()); setState(() {}); }
ListView.builder的itemCount可直接写machineList.length,因为前面已经判断了列表非空。
内容的提问来源于stack exchange,提问作者Minimumspace
相关产品推荐
相关产品推荐

