Flutter名言APP开发求助:类型不匹配错误及随机显示功能异常排查
解决Flutter中"Expected a value of type 'int', but got one of type 'String'"错误及名言APP功能修复
让我们一步步排查并解决你的问题,这个错误的根源是数据类型处理混乱,加上FutureBuilder的使用方式不对,具体问题和修复方案如下:
核心问题分析
FutureBuilder的误用
你已经在initState里调用了fetchQuoteData()拉取数据并存在QuotesList里,但又在build里用FutureBuilder再次调用fetchQuoteData()——更关键的是,fetchQuoteData()没有返回任何数据(它是void类型),所以snapshot.data是null,你把它转成字符串"null"后,试图把这个字符串当成列表/Map来用,这就直接导致了类型错误。变量逻辑混乱
- 你把
snapshot.data.toString()赋值给_data,然后用_data.length生成随机索引,但_data是字符串,后续又试图用_data[c]['text']访问Map属性,完全不符合数据结构逻辑。 - 底部按钮的
setState是空的,点击后不会触发重新生成随机名言的逻辑。
- 你把
命名不规范(非致命但影响可读性)
Dart推荐小驼峰命名变量(比如quotesList而非QuotesList),这样代码更易维护。
修复步骤
1. 移除多余的FutureBuilder,直接使用已加载的quotesList
既然initState已经初始化了数据,我们可以直接基于quotesList构建UI,同时处理数据未加载完成的状态(比如显示加载指示器)。
2. 修正随机索引的生成逻辑
直接基于quotesList的长度生成随机索引,并且把当前选中的索引存在状态变量里,点击按钮时更新这个索引并触发setState。
3. 修复按钮的点击逻辑
在按钮的onPressed里更新随机索引,触发重绘显示新的名言。
4. 规范变量命名
调整所有变量为小驼峰命名,符合Dart代码规范。
修复后的完整代码
class _MyAppState extends State<MyApp> { List<Map<String, dynamic>> quotesList = []; int? currentQuoteIndex; // 存储当前显示的名言索引 final url = "https://type.fit/api/quotes"; fetchQuoteData() async { Response response = await get(Uri.parse(url)); final quotesData = jsonDecode(response.body); setState(() { quotesList = List<Map<String, dynamic>>.from(quotesData); // 初始化时随机选一个名言 currentQuoteIndex = Random().nextInt(quotesList.length); }); } @override void initState() { fetchQuoteData(); super.initState(); } // 生成新的随机名言索引 void _generateRandomQuote() { if (quotesList.isNotEmpty) { setState(() { currentQuoteIndex = Random().nextInt(quotesList.length); }); HapticFeedback.heavyImpact(); } } @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('assets/pic/image4.jpg'), fit: BoxFit.cover, colorFilter: ColorFilter.mode( Colors.black.withOpacity(0.6), BlendMode.darken)), ), child: Scaffold( backgroundColor: Colors.transparent, body: Center( child: quotesList.isEmpty ? CircularProgressIndicator(color: Colors.white) // 数据加载中显示指示器 : UiCard(currentQuoteIndex!), ), bottomNavigationBar: BottomAppBar( color: Colors.indigo.shade900, child: Container( margin: const EdgeInsets.only(left: 40.0, right: 40.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisSize: MainAxisSize.max, children: <Widget>[ IconButton( tooltip: 'Random Quotes', icon: Icon(Icons.format_quote_outlined), iconSize: 40, color: Colors.white, onPressed: _generateRandomQuote, // 调用生成随机名言的方法 ), ], ), ), ), ), ); } Widget UiCard(int index){ final quote = quotesList[index]; return Container( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Padding( padding: const EdgeInsets.all(25.0), child: Text(quote['text'] ?? "No quote available", style: TextStyle( fontWeight: FontWeight.w300, fontSize: 22.0, color: Colors.white, fontFamily: 'Raleway-Italic', fontStyle: FontStyle.italic,), textScaleFactor: 2.0,) ), Text(quote['author'] ?? "Unknown Author", style: TextStyle( fontWeight: FontWeight.w500, color: Colors.white, fontFamily: 'Raleway-Bold', fontSize: 18.0 ), textAlign: TextAlign.center, ), ], ), ), ); } }
额外优化点
- 增加了数据加载状态的处理(显示
CircularProgressIndicator),避免数据未加载完成时出现空指针错误。 - 给名言和作者字段增加了空值判断(
??运算符),防止API返回的部分数据缺失导致崩溃。 - 把生成随机索引的逻辑抽成单独方法
_generateRandomQuote,代码更清晰。
内容的提问来源于stack exchange,提问作者Hossain Abeer
相关产品推荐
相关产品推荐

