Flutter中setState首次点击无法更新游戏列表问题求助
问题:首次点击“获取更多”无法更新游戏列表,二次点击才生效
页面展示游戏列表,点击“获取更多”按钮加载下一页数据,但首次点击时列表无变化,第二次点击才能成功更新。尝试在setState后调用_loadData(),问题依旧。
提供的代码
HomePage State代码
class _HomePageState extends State<HomePage> { bool _isLoading = true; int _currentPage = 0; @override void initState() { super.initState(); Provider.of<GameController>( context, listen: false, ).loadGames(_currentPage).then((value) { setState(() => _isLoading = false); }); } _loadData() async { await Provider.of<GameController>( context, listen: false, ).loadGames(_currentPage); } @override Widget build(BuildContext context) { final gameController = Provider.of<GameController>(context, listen: false); final List<Game> loadGames = gameController.games; final deviceSize = MediaQuery.of(context).size; return Scaffold( appBar: AppBar( title: const Text('Games'), centerTitle: true, actions: const [LogoutButton()], ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : Column( mainAxisSize: MainAxisSize.max, children: [ Expanded( child: SizedBox( height: deviceSize.height * 0.75, child: SingleChildScrollView( child: Column( children: [ GameList(loadGames), Container( margin: const EdgeInsets.only(bottom: 10.0), child: ElevatedButton( onPressed: () { print(_currentPage); setState(() { _currentPage++; _loadData(); }); print(_currentPage); }, child: const Text('Get more...'), ), ), ], ), ), ), ), ], ), ); } }
GameController的loadGames函数
Future<void> loadGames(int currentPage) async { final url = '${Constants.urlGame}?page=$currentPage'; SharedPreferences prefs = await SharedPreferences.getInstance(); final token = prefs.getString('token'); final response = await http.get( Uri.parse(url), headers: {'Authorization': '$token'}, ); if (response.statusCode == 200) { final jsonResponse = jsonDecode(response.body); final gameList = GameList.fromJson(jsonResponse); final List<Game> games = gameList.games; _games.clear(); _games.addAll(games); notifyListeners(); } else { print( response.statusCode, ); } }
问题根源
- 数据加载逻辑错误:
loadGames里的_games.clear()会清空已有数据,每次加载新页都是替换而非追加,违背“获取更多”的需求。 - 页面未监听Provider变化:
build方法中用listen: false获取GameController,导致notifyListeners()触发时页面不会重新构建,无法感知数据更新。 - 异步调用顺序问题:
setState中同步调用异步的_loadData(),setState立即完成但数据加载未结束,页面不会等待加载完成就刷新,首次点击后数据未更新导致无变化。
修复方案
1. 修改loadGames实现数据追加
移除_games.clear(),直接追加新页数据:
Future<void> loadGames(int currentPage) async { final url = '${Constants.urlGame}?page=$currentPage'; SharedPreferences prefs = await SharedPreferences.getInstance(); final token = prefs.getString('token'); final response = await http.get( Uri.parse(url), headers: {'Authorization': '$token'}, ); if (response.statusCode == 200) { final jsonResponse = jsonDecode(response.body); final gameList = GameList.fromJson(jsonResponse); final List<Game> games = gameList.games; // 移除clear,直接追加新数据 _games.addAll(games); notifyListeners(); } else { print(response.statusCode); } }
2. 让页面监听Provider数据变化
去掉listen: false,使页面能监听数据更新自动刷新:
@override Widget build(BuildContext context) { // 监听GameController的变化,数据更新时自动重建页面 final gameController = Provider.of<GameController>(context); final List<Game> loadGames = gameController.games; final deviceSize = MediaQuery.of(context).size; // 后续代码保持不变 }
3. 修正按钮点击的异步逻辑
无需在setState内调用异步函数,先递增页码再加载数据,页面会因Provider监听自动刷新:
ElevatedButton( onPressed: () async { _currentPage++; await _loadData(); }, child: const Text('Get more...'), ),
4. 可选:添加加载状态防重复点击
添加_isLoadingMore变量,避免用户重复点击:
// 在State类中添加变量 bool _isLoadingMore = false; // 修改_loadData函数 _loadData() async { if (_isLoadingMore) return; setState(() { _isLoadingMore = true; }); await Provider.of<GameController>( context, listen: false, ).loadGames(_currentPage); setState(() { _isLoadingMore = false; }); } // 修改按钮 ElevatedButton( onPressed: _isLoadingMore ? null : () async { _currentPage++; await _loadData(); }, child: _isLoadingMore ? const CircularProgressIndicator(color: Colors.white) : const Text('Get more...'), ),
完成以上修改后,首次点击“获取更多”即可正确追加新游戏数据,页面自动刷新显示。
内容的提问来源于stack exchange,提问作者wendelfl
相关产品推荐
相关产品推荐

