Flutter对接OdooApi处理Map<String,List<Object>>时空值调用[]报错如何解决
问题根因汇总
- 1、CheckScreen参数命名不匹配,跳转时传入
num_or参数,但类定义的接收字段为id,导致widget.num_or取值为null - 2、
_getDataFromServer方法声明返回类型为Future<OdooResponse>,但实际返回的是result.getResult()['records'](列表类型),类型不匹配导致返回值异常 - 3、未对空返回、认证失败场景做非空判断,空值后续被调用
[]方法时报错 - 4、文本框输入的
num_or是字符串类型,Odoo的id字段为int类型,查询条件类型不匹配会导致返回空记录
分步修复方案
第一步:修正CheckScreen参数定义
修改check_screen.dart中CheckScreen类的构造参数,和跳转传入的参数名对齐:
class CheckScreen extends StatefulWidget { // 改成接收num_or参数 final String num_or; const CheckScreen({super.key, required this.num_or}); @override _CheckScreenState createState() => _CheckScreenState(); } // 状态类不需要单独传id,直接通过widget.num_or取值即可,删掉状态类的id构造参数 class _CheckScreenState extends State<CheckScreen> { var dt; // 删掉这行:_CheckScreenState({this.id});
第二步:修正_getDataFromServer方法的返回类型与逻辑
首先调整返回类型为Future<List<dynamic>>,增加非空判断、参数类型转换:
Future<List<dynamic>> _getDataFromServer(String idStr) async { // 先把字符串id转成int类型,匹配Odoo字段类型 final int? id = int.tryParse(idStr); if (id == null) return []; final auth = await client.authenticate(email, password, database); if (!auth.isSuccess) { print("Login Gagal"); return []; } final result = await client.searchRead('account.invoice', [ ['id', '=', id] ], [ 'id', 'name', 'number', 'service_source', 'origin_invoice' ]); final records = result.getResult()?['records']; // 非空判断,为空返回空列表 return records ?? []; }
第三步:修正FutureBuilder逻辑,支持列表展示
如果需要用ListView展示返回的记录,替换build方法里的FutureBuilder逻辑:
@override Widget build(BuildContext context) { return Scaffold( body: Center( child: FutureBuilder<List<dynamic>>( future: _getDataFromServer(widget.num_or), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } final records = snapshot.data ?? []; if (records.isEmpty) { return const Center(child: Text('未查询到匹配数据')); } // 用ListView展示数据 return ListView.builder( itemCount: records.length, itemBuilder: (context, index) { final item = records[index]; return ListTile( title: Text(item['name'] ?? '无名称'), subtitle: Text('编号:${item['number'] ?? ''},来源:${item['origin_invoice'] ?? ''}'), trailing: Text('ID: ${item['id']}'), ); }, ); }, ), ), ); }
内容的提问来源于stack exchange,提问作者Imad fed
相关产品推荐
相关产品推荐

