You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter下拉框绑定数据库值时遇空安全调用错误求助

问题:DropdownButton从数据库取值时的空安全错误

错误出现在以下代码行:

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属性用法理解错误:

  1. machineList[index].serienummer是单个String?字段,不是列表,不能直接用来生成下拉选项,需要遍历整个machineList提取所有有效serienummer值。
  2. 必须处理空安全,过滤掉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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:51:29