Flutter中如何从JSON文件获取数据填充GridView.builder?
用JSON中MORE_APPS数据填充GridView.builder的实现方案
步骤1:定义数据模型类
先创建对应MORE_APPS数组元素的模型类,方便数据管理:
class MoreApp { final String title; final String img; final String url; final String country; MoreApp({ required this.title, required this.img, required this.url, required this.country, }); // 从JSON对象转换为模型实例 factory MoreApp.fromJson(Map<String, dynamic> json) { return MoreApp( title: json['title'] ?? '', img: json['img'] ?? '', url: json['url'] ?? '', country: json['country'] ?? '', ); } }
步骤2:加载并解析JSON数据
根据你的JSON来源(本地资产或网络)选择对应方式:
方式1:加载本地JSON文件
- 先在
pubspec.yaml中配置资产路径:
flutter: assets: - assets/your_data.json # 替换成你的JSON文件实际路径
- 编写加载解析函数:
import 'dart:convert'; import 'package:flutter/services.dart'; Future<List<MoreApp>> loadLocalMoreApps() async { // 读取本地JSON文件内容 final String jsonString = await rootBundle.loadString('assets/your_data.json'); final Map<String, dynamic> data = json.decode(jsonString); // 提取MORE_APPS数组并转换为模型列表 List<dynamic> moreAppsJson = data['MORE_APPS']; return moreAppsJson.map((appJson) => MoreApp.fromJson(appJson)).toList(); }
方式2:从网络加载JSON数据
- 先在
pubspec.yaml添加http依赖:
dependencies: flutter: sdk: flutter http: ^1.1.0
- 编写网络请求解析函数:
import 'dart:convert'; import 'package:http/http.dart' as http; Future<List<MoreApp>> fetchRemoteMoreApps() async { final response = await http.get(Uri.parse('你的JSON文件网络地址')); if (response.statusCode == 200) { final Map<String, dynamic> data = json.decode(response.body); List<dynamic> moreAppsJson = data['MORE_APPS']; return moreAppsJson.map((appJson) => MoreApp.fromJson(appJson)).toList(); } else { throw Exception('加载数据失败'); } }
步骤3:用GridView.builder展示数据
结合FutureBuilder处理异步加载状态,最终实现网格视图:
import 'package:flutter/material.dart'; class MoreAppsGrid extends StatefulWidget { const MoreAppsGrid({super.key}); @override State<MoreAppsGrid> createState() => _MoreAppsGridState(); } class _MoreAppsGridState extends State<MoreAppsGrid> { late Future<List<MoreApp>> _moreAppsFuture; @override void initState() { super.initState(); // 选择本地加载或网络加载 _moreAppsFuture = loadLocalMoreApps(); // _moreAppsFuture = fetchRemoteMoreApps(); } @override Widget build(BuildContext context) { return FutureBuilder<List<MoreApp>>( future: _moreAppsFuture, builder: (context, snapshot) { if (snapshot.hasData) { final List<MoreApp> moreApps = snapshot.data!; return GridView.builder( padding: const EdgeInsets.all(16), // 网格布局配置:每行2个,设置间距和宽高比 gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 0.8, ), itemCount: moreApps.length, itemBuilder: (context, index) { final MoreApp app = moreApps[index]; return Card( elevation: 2, child: Column( children: [ // 加载应用图片,处理加载失败场景 Expanded( child: Image.network( app.img, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return const Icon(Icons.broken_image, size: 40); }, ), ), // 应用标题 Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Text( app.title, textAlign: TextAlign.center, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 14, ), ), ), // 跳转按钮(需添加url_launcher依赖实现跳转) TextButton( onPressed: () { // 示例:打开应用链接 // launchUrl(Uri.parse(app.url)); }, child: const Text('获取应用'), ), ], ), ); }, ); } else if (snapshot.hasError) { return Center(child: Text('加载出错:${snapshot.error}')); } // 加载中状态 return const Center(child: CircularProgressIndicator()); }, ); } }
注意事项
- JSON格式修正:你提供的JSON末尾有多余的逗号(
"MORE_APPS": [...],中的逗号),需要删除,否则会导致解析失败。 - 链接跳转实现:如果需要点击按钮打开链接,需添加
url_launcher依赖,并在Android/iOS项目中配置相应权限。 - 图片加载优化:如果图片是本地资产,需将
Image.network替换为Image.asset,并确保图片路径正确。
内容的提问来源于stack exchange,提问作者Allen John
相关产品推荐
相关产品推荐

