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

首次进入注册页时可选参数为空引发NoSuchMethodError问题

问题描述

我在Dart中定义了如下结构的对象:

{ name: , lastname: , phone: , email: }

并通过以下代码在Flutter的RegistrationPage中打印该对象:

class RegistrationPage extends StatefulWidget {
  // 接收从第一页传递过来的数据用于注册
  final info;
  const RegistrationPage({this.info,Key? key}) : super(key: key);

  @override
  State<RegistrationPage> createState() => _RegistrationPage();
}


class _RegistrationPage extends State<RegistrationPage> {

  @override
  void initState() {
    super.initState();
    logUserInfo();
  }

  void logUserInfo() {
    var userFilling = widget.info;
    log("$userFilling");
  }
}

用户完成注册页填写后需继续填写其他页面才可完成注册,同时支持返回上一页。当用户返回注册页时,我希望通过widget.info填充之前填写的内容(示例如下)以支持编辑:

{ name: "firstname", lastname: "lastname" , phone: +99999, email: "email@email.com"}

首次进入注册页时,该可选对象为空。

但当我尝试通过以下代码为文本控制器赋值时:

myController.text = (widget.info['email'] != null)?widget.info['email']:"",;

出现错误:

NoSuchMethodError: The method '[]' was called on null. Receiver: null. Tried calling [](email)

请问如何实现:若参数对象为空则保持文本控制器为空,若不为空则填充对应内容,同时避免上述空指针错误?

解决方案

错误根源是首次进入页面时widget.info本身为null,直接调用widget.info['email']等于在null上执行索引操作,触发空指针异常。以下是几种可行的解决方式:

方法1:利用空安全运算符简化判断

使用Dart的可选链运算符(?.)和空合并运算符(??),先判断widget.info是否非空,再读取字段:

myController.text = widget.info?['email'] ?? "";
  • widget.info?['email']:如果widget.info不为null,读取email字段;若为null,整个表达式返回null
  • ?? "":若前面的结果为null,就用空字符串替代

方法2:给info设置默认空Map

在RegistrationPage的构造函数中,给info设置默认值为空Map,确保widget.info永远不会是null:

class RegistrationPage extends StatefulWidget {
  // 明确指定类型为Map,提升类型安全性
  final Map<String, dynamic> info;
  // 设置默认值为空不可变Map
  const RegistrationPage({this.info = const {}, Key? key}) : super(key: key);

  @override
  State<RegistrationPage> createState() => _RegistrationPage();
}

之后赋值时无需再判断info是否为null,直接写:

myController.text = widget.info['email'] ?? "";

方法3:使用类型安全的模型类(推荐)

如果项目规模较大,建议定义专用的用户信息模型类,替代原始Map,既避免类型错误,又能更优雅处理空值:

class UserInfo {
  final String? name;
  final String? lastName;
  final String? phone;
  final String? email;

  const UserInfo({this.name, this.lastName, this.phone, this.email});

  // 从Map转换为模型类的工厂方法
  factory UserInfo.fromMap(Map<String, dynamic>? map) {
    if (map == null) {
      return const UserInfo();
    }
    return UserInfo(
      name: map['name'],
      lastName: map['lastname'],
      phone: map['phone'],
      email: map['email'],
    );
  }
}

修改RegistrationPage的参数类型:

class RegistrationPage extends StatefulWidget {
  final UserInfo info;
  // 默认创建空的UserInfo对象
  const RegistrationPage({this.info = const UserInfo(), Key? key}) : super(key: key);

  @override
  State<RegistrationPage> createState() => _RegistrationPage();
}

赋值时直接调用模型类属性:

myController.text = widget.info.email ?? "";

这种方式代码可读性更高,维护成本更低,适合中大型项目。

内容的提问来源于stack exchange,提问作者umarkaa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:38:14