Flutter/Dart:如何在ListView中正常展示JSON响应内容而非拆分字符
Flutter ListView展示JSON内容时拆分为单个字符的解决办法
我来帮你搞定这个问题~首先咱们得先弄明白为什么会出现这种情况:
问题根源
你现在缓存的是单个字符串,而ListView.builder里用了snapshot.data.length——这里的length其实是字符串的字符长度,所以ListView会把每个字符都当作一个独立的列表项来渲染,自然就把完整消息拆成单个字符展示了。
接下来根据你的业务场景,给你两种解决方案:
方案1:当前场景(仅单条消息)
如果你的业务逻辑里只会返回一条符合条件的消息,那直接调整展示代码就行,把单个字符串包装成一个长度为1的列表,这样ListView就只会渲染一个ListTile,显示完整内容:
修改messageBoard页面里的FutureBuilder部分:
future: ReadCache.getString(key: "cache3"), builder: (context, snapshot) { if (snapshot.hasData) { // 把单个字符串包装成列表,确保只有一个列表项 final messages = [snapshot.data!]; return ListView.builder( itemCount: messages.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(5.0), child: ListTile( title: Text( messages[index], style: GoogleFonts.poppins( textStyle : const TextStyle( fontWeight: FontWeight.normal, fontSize: 20, ), ) ), tileColor: Colors.blueGrey[200], shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), ); }); } else { return const Text("No Data"); } },
方案2:兼容多条消息的场景
如果后续业务可能返回多条符合条件的消息,那最好从缓存环节就改成存储列表,这样扩展性更好:
第一步:修改获取并缓存数据的代码
把原来提取单条消息的逻辑改成提取所有符合条件的消息到列表,然后转成JSON字符串缓存:
onPressed: () async{ var newMessage = await (ReadCache.getString(key: 'cache1')); var response = await http.get( Uri.parse( 'http://192.168.1.8:8080/HongLeong/MENU_REQUEST.do?_dc=1657717579436&table_id=25018&fk_table_id=25004&id_MenuAction=3&reset_context=1&ViewType=MENU_REQUEST&gui_open_popup=1&id_Window=5&activeWindowId=mw_5&noOrigUserDate=true&LocalDate=20220713&LocalTime=21061900&TimeZone=Asia/Shanghai&UserDate=0&UserTime=0&server_name=OPRISK_DATACOLLECTOR&key_id_list=&cell_context_id=0&id_Desktop=100237&operation_key=1000007&operation_sub_num=-1&is_json=1&is_popup=0&is_search_window=0&ccsfw_conf_by_user=0&is_batch=0&previousToken=1657717554097&historyToken=1657717579434&historyUrl=1'), headers: {HttpHeaders.cookieHeader: newMessage}, ); ResponseModel responseModel = ResponseModel.fromJson(jsonDecode(response.body)); final listNode = responseModel.response.genericListAnswer.listNode; // 提取所有符合条件的消息到列表 List<String> messages = listNode .map((x) => x.toJson()) .where((json) => json['field'][5]['field_value'] == 'Loss Event') .map((json) => json['field'][0]['field_value']) .toList(); // 将列表转成JSON字符串存入缓存 await WriteCache.setString(key: 'cache3', value: jsonEncode(messages)); print(messages); Navigator.of(context).push(MaterialPageRoute( builder: (context) => messageBoard())); }
第二步:修改展示代码
读取缓存后解析成列表,再用ListView渲染每个消息:
body: Row( children: [ Expanded( child: FutureBuilder( // 读取缓存并解析为字符串列表 future: ReadCache.getString(key: "cache3").then((data) => jsonDecode(data) as List<String>), builder: (context, snapshot) { if (snapshot.hasData && snapshot.data!.isNotEmpty) { return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(5.0), child: ListTile( title: Text( snapshot.data![index], style: GoogleFonts.poppins( textStyle : const TextStyle( fontWeight: FontWeight.normal, fontSize: 20, ), ) ), tileColor: Colors.blueGrey[200], shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), ); }); } else { return const Text("No Data"); } }, ), ), ], ),
内容的提问来源于stack exchange,提问作者JoshuaaMarkk
相关产品推荐
相关产品推荐

