Flutter FutureBuilder无法填充值 报错Future<dynamic>不是Future<String>子类型
问题原因
- 异步函数类型不匹配:
getShopLength()没有显式声明返回类型,默认返回Future<dynamic>,且实际返回的是int类型的列表长度,和FutureBuilder<String>声明的Future<String>类型要求冲突,直接触发类型报错。 - FutureBuilder使用逻辑错误:你将FutureBuilder定义在build方法中但没有将其加入Widget渲染树,同时试图在builder回调中修改外部局部变量
valueShop,这种写法无效:build方法执行时会先返回Scaffold,此时Future还未完成,valueShop永远是初始值"0",定义的FutureBuilder完全不会生效。
解决方法
第一步:修正异步函数返回类型
给getShopLength()添加显式返回类型,同时将返回的长度转为字符串匹配后续使用要求:
// main.dart中修改函数定义 Future<String> getShopLength() async { final queryParameters = { 'api_key': '123', 'user_id': '123', 'lat': '123', 'long': '123', 'km': '123', }; var response = await http.get(Uri.https('google.de','getSth', queryParameters)); var jsonData = jsonDecode(response.body); List<Shops> shops = []; for(var x in jsonData) { Shops shop = Shops(x['name'], x['slogan']); shops.add(shop); } // 转为String返回 return shops.length.toString(); }
第二步:调整FutureBuilder的使用逻辑
将整个Scaffold放到FutureBuilder的builder回调中,依赖异步数据的组件只有在拿到数据后再渲染,加载阶段可以显示加载占位:
// home.dart中修改build方法 @override Widget build(BuildContext context) { return FutureBuilder<String>( future: getShopLength(), builder: (context, snapshot) { // 加载中状态 if (!snapshot.hasData) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } // 拿到数据后渲染完整页面 final valueShop = snapshot.data!; return Scaffold( appBar: buildSearchBar(context), body: Padding( padding: const EdgeInsets.fromLTRB(10.0, 0, 10.0, 0), child: ListView( children: <Widget>[ SizedBox(height: 20.0), buildRestaurantRow('Top Angebote', context, valueShop), SizedBox(height: 10.0), buildRestaurantList(context), SizedBox(height: 10.0), buildCategoryRow('Nach Kategorie', context), SizedBox(height: 10.0), buildCategoryList(context), SizedBox(height: 20.0), buildCategoryRow('Deine Favoriten', context), SizedBox(height: 10.0), buildFriendsList(), SizedBox(height: 30.0), ], ), ), ); }, ); }
可选优化
如果不需要加载时替换整个页面,只需要替换buildRestaurantRow的位置,可以只把这个组件包裹在FutureBuilder里,其他部分正常渲染即可。
内容的提问来源于stack exchange,提问作者piguy
相关产品推荐
相关产品推荐

