Flutter中ListView Builder无内容返回,疑与Provider调用有关
问题与解决方案
问题描述
即使将ListView.builder的itemCount设置为固定数值3,页面仍无法显示内容;但注释掉页面中获取TeamServices的代码以及Column内相关调用后,文本“Hello”可以正常显示。控制台能正常打印TeamServices中获取到的数据,怀疑问题出在final teamServices = Provider.of<TeamServices>(context);这行代码上。
代码片段
main.dart
import 'package:firebase_api/pages/home_page.dart'; import 'package:firebase_api/services/team_services.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() => runApp(const AppState()); class AppState extends StatelessWidget { const AppState({super.key}); @override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider(create: (_)=> TeamServices()) ], child: const MyApp(), ); } } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo' ), home: const HomePage(), ); } }
HomePage.dart
import 'package:firebase_api/services/team_services.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { final teamServices = Provider.of<TeamServices>(context); return Scaffold( appBar: AppBar( centerTitle: true, title: const Text('Firebase'), backgroundColor: Colors.blue[400], titleTextStyle: TextStyle(color: Colors.white), ), body: ListView.builder( itemCount: 3, //teamServices.listTeams.length, shrinkWrap: true, itemBuilder: (BuildContext context, int index) { return Column( children: [ Text('Hello'), // Text(teamServices.listTeams.length.toString()), // Text(teamServices.listTeams[index].customer) ], ); }, ), ); } }
team_services.dart
import 'dart:convert'; import 'package:firebase_api/models/teams_model.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class TeamServices extends ChangeNotifier { final String _urlBase = 'test-ab11a-default-rtdb.firebaseio.com'; final List<Team> listTeams = []; TeamServices() { getTeams(); } Future <List<Team>> getTeams() async { final teamUrl = Uri.https(_urlBase, 'orders.json'); final response = await http.get(teamUrl); // print(response.body); final Map<String, dynamic> obj = json.decode(response.body); obj.forEach((key, value) { final team = Team.fromMap(value); team.id = key; //.toString(); // as int?; listTeams.add(team); }); // print(listTeams[5].price); print(listTeams.length); return listTeams; } }
解决方案
1. 修复main.dart的语法错误
MyApp中MaterialApp的构造存在语法错误,home参数被错误地写在了MaterialApp的括号外部,导致Widget树结构异常。修正后代码如下:
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', home: const HomePage(), // 将home参数移至MaterialApp括号内 ); } }
2. 修复TeamServices的状态通知问题
TeamServices中获取数据后未调用notifyListeners(),无法通知UI更新数据变化。在getTeams方法末尾添加通知代码:
Future <List<Team>> getTeams() async { final teamUrl = Uri.https(_urlBase, 'orders.json'); final response = await http.get(teamUrl); final Map<String, dynamic> obj = json.decode(response.body); obj.forEach((key, value) { final team = Team.fromMap(value); team.id = key; listTeams.add(team); }); print(listTeams.length); notifyListeners(); // 通知UI更新状态 return listTeams; }
说明
- 第一个错误直接导致页面Widget树构建失败,所以即使
ListView设置了固定itemCount也无法显示内容;注释掉Provider相关代码后,错误的Widget结构偶然绕过了语法错误的影响,才显示出“Hello”。 - 第二个错误会导致数据加载完成后,UI无法感知到
listTeams的变化,即使控制台能打印数据,页面也不会更新显示列表内容。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

