Flutter开发求助:List<Widget>?无法赋值给List<Widget>错误
问题解决:List? 无法赋值给 List
错误原因
pokeHub 和 pokeHub.pokemon 都是可空类型(声明时带?),链式调用 pokeHub?.pokemon?.map(...).toList() 的结果是List<Widget>?,但 GridView.count 的children参数要求非空的List<Widget>,类型不匹配导致报错。
修复方案
1. 基础修复:给可空列表兜底
使用空合并运算符??,当pokeHub?.pokemon为null时返回空列表,直接解决类型不匹配问题:
children: pokeHub?.pokemon?.map<Widget>((e) => Card(child: Text(e.name))).toList() ?? []
2. 优化:添加加载状态处理
因为fetchData是异步方法,初始状态下pokeHub为null,直接显示GridView会出现空页面,建议增加加载状态判断:
body: pokeHub == null ? const Center(child: CircularProgressIndicator()) : GridView.count( crossAxisCount: 2, children: pokeHub!.pokemon!.map<Widget>((e) => Card(child: Text(e.name))).toList() ),
这里用!断言是因为已经通过pokeHub == null排除了空值情况,确保后续调用安全。
3. 关键:初始化时触发数据请求
必须在initState中调用fetchData,否则页面永远不会加载数据:
@override void initState() { super.initState(); fetchData(); }
完整修复代码
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; // 导入你的PokeHub类定义 final url = "https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json"; PokeHub? pokeHub; Future fetchData() async { final response = await http.get(Uri.parse(url)); final jsonData = jsonDecode(response.body); pokeHub = PokeHub.fromJson(jsonData); } @override void initState() { super.initState(); fetchData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Pokemon App'), backgroundColor: Colors.cyan, ), body: pokeHub == null ? const Center(child: CircularProgressIndicator()) : GridView.count( crossAxisCount: 2, children: pokeHub!.pokemon!.map<Widget>((e) => Card(child: Text(e.name))).toList() ), drawer: const Drawer(), floatingActionButton: FloatingActionButton( onPressed: fetchData, // 点击可重新加载数据 backgroundColor: Colors.cyan, child: const Icon(Icons.refresh), ), ); }
进阶优化:使用FutureBuilder管理异步状态
替代手动维护pokeHub状态,用FutureBuilder更优雅地处理异步加载、错误状态:
// 修改fetchData为返回Future<PokeHub> Future<PokeHub> fetchData() async { final response = await http.get(Uri.parse(url)); final jsonData = jsonDecode(response.body); return PokeHub.fromJson(jsonData); } // 替换body部分 body: FutureBuilder<PokeHub>( future: fetchData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('加载失败: ${snapshot.error}')); } else { return GridView.count( crossAxisCount: 2, children: snapshot.data!.pokemon!.map<Widget>((e) => Card(child: Text(e.name))).toList() ); } }, )
内容的提问来源于stack exchange,提问作者Dwitio Ahmad Pranoto
相关产品推荐
相关产品推荐

