Flutter数据展示报错:'String'不是'int'类型的index子类型
问题描述
我想把Postman里的API数据展示到Flutter应用中,已经成功获取数据并在终端打印,但没法在模拟器里展示,报错如下:
Exception has occurred._TypeError (type 'String' is not a subtype of type 'int' of 'index')
错误出现在value: data[index]['kode']和value: data[index]['nama']这两行,以下是我的代码:
product.dart
class _pageSuccessState extends State<pageSuccess> { var data; Future<void> getUserApi() async { final response = await http.get( Uri.parse('http://10.0.2.2:8000/api/produk'), headers: headersWithToken, ); var encodeFirst = json.encode(response.body.toString()); if (response.statusCode == 200) { data = jsonDecode(encodeFirst).toString(); print(data); print('product success'); } else { print('product failed'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text('Api Course'), ), body: Column( children: [ Expanded( child: FutureBuilder( future: getUserApi(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Text('Loading'); } else { return ListView.builder( itemCount: data.length, itemBuilder: (context, index) { return Card( child: Column( children: [ ReusbaleRow( title: 'kode', value: data[index]['kode'].toString(), ), ReusbaleRow( title: 'nama', value: data[index]['nama'].toString(), ), ], ), ); }); } }, ), ) ], ), ); } } class ReusbaleRow extends StatelessWidget { String title; String value; ReusbaleRow({Key? key, required this.title, required this.value}) : super(key: key); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title as String), Text(value as String), ], ), ); } }
问题原因与修复方案
核心问题
你的data最终被转换成了字符串类型,但你却把它当成数组来使用(data[index]),这就导致了类型不匹配的错误。问题出在数据解析的冗余操作上:
var encodeFirst = json.encode(response.body.toString()); data = jsonDecode(encodeFirst).toString();
response.body本身就是API返回的JSON字符串,不需要额外用toString()包裹,更不需要先编码再解码,这完全是多余操作。- 最后调用的
.toString()直接把解析后的数组/对象转换成了纯文本字符串,导致data变成一串字符,自然无法用下标[index]访问元素。
修复步骤
修正数据解析逻辑
把getUserApi方法里的解析代码改成以下形式,直接解析原始响应体:Future<void> getUserApi() async { final response = await http.get( Uri.parse('http://10.0.2.2:8000/api/produk'), headers: headersWithToken, ); if (response.statusCode == 200) { // 直接解析response.body,去掉冗余的encode和toString操作 data = jsonDecode(response.body); print(data); print('product success'); } else { print('product failed'); } }这样
data就会保持API返回的数组类型(假设接口返回的是列表数据),可以正常用data[index]访问单个元素。避免重复请求
当前每次页面build都会调用getUserApi(),会导致重复发起API请求。建议在initState中提前初始化请求Future:late Future<void> _fetchDataFuture; @override void initState() { super.initState(); _fetchDataFuture = getUserApi(); } // 在FutureBuilder中使用初始化好的Future FutureBuilder( future: _fetchDataFuture, // ...其他代码不变 )增加空数据判断
在渲染列表前,先判断data是否为空或无效,避免空指针异常:else { if (data == null || data.isEmpty) { return Center(child: Text('暂无数据')); } return ListView.builder( itemCount: data.length, // ...其他代码不变 ); }简化组件代码
ReusbaleRow组件中的as String转换是多余的,因为参数已经定义为String类型,直接使用即可:Text(title), Text(value),
内容的提问来源于stack exchange,提问作者Raymond Pratama S
相关产品推荐
相关产品推荐

