Flutter中List.Builder触发范围错误问题求助
解决Flutter ListView.Builder触发范围错误的问题
我来帮你梳理下问题并给出解决方案,你遇到的范围错误核心原因是初始阶段tasks列表为空,同时代码里还有几个逻辑和状态管理的小问题,咱们一步步来修复:
问题拆解
- 初始化时
listView可能为null,且tasks为空,直接渲染会触发范围错误 initState里多余的setState包裹异步方法,毫无意义getRecordsAndDisplay里的空值判断逻辑错误:if (len != null || len != 0)应该用&&,否则这个条件永远为true- 直接在异步方法里创建
ListView.builder并赋值给变量,不符合Flutter的状态管理逻辑,应该让build方法根据状态动态构建UI
解决方案步骤
1. 修复初始化逻辑
首先修正initState,不需要用setState包裹异步方法,直接调用即可:
@override void initState() { super.initState(); // 直接调用异步方法,无需外层setState getRecordsAndDisplay(); }
2. 修正数据获取方法的逻辑
重构getRecordsAndDisplay,只负责获取数据并更新tasks和checkValue,不要在里面创建ListView:
void getRecordsAndDisplay() async { final records = await Firestore.instance.collection('tasks').getDocuments(); // 先清空旧数据,避免重复添加 tasks.clear(); checkValue.clear(); for (var record in records.documents) { if (record.data['phone'] == '1') { // 先判断task是否存在且是数组 if (record.data['task'] != null && record.data['task'] is List) { List taskList = record.data['task']; // 遍历添加任务,同时同步初始化checkValue for (String task in taskList) { tasks.add(task); checkValue.add(false); } } } } // 数据更新后通知UI重建 setState(() {}); }
3. 在build方法中动态构建ListView
把ListView.builder移到build方法里,同时处理加载状态和空数据状态,避免范围错误:
首先在类里添加加载状态变量:
List<String> tasks = []; List<bool> checkValue = []; bool _isLoading = true;
然后修改getRecordsAndDisplay方法,结束时更新加载状态:
void getRecordsAndDisplay() async { final records = await Firestore.instance.collection('tasks').getDocuments(); tasks.clear(); checkValue.clear(); for (var record in records.documents) { // ... 保留之前的遍历逻辑 } setState(() { _isLoading = false; }); }
最后替换build里的Flexible部分:
Flexible( child: Container( padding: EdgeInsets.only(left: 10.0, right: 10.0), height: MediaQuery.of(context).size.height, child: _isLoading ? Center(child: CircularProgressIndicator(color: Colors.white)) // 加载中显示圈圈 : tasks.isEmpty ? Center(child: Text('暂无任务,点击右上角添加吧~', style: TextStyle(color: Colors.white))) // 空数据提示 : ListView.builder( scrollDirection: Axis.vertical, itemCount: tasks.length, itemBuilder: (BuildContext context,int index) { return Container( margin: EdgeInsets.only(bottom: 10.0), decoration: BoxDecoration( color: Colors.deepPurple[700], borderRadius: BorderRadius.all(Radius.circular(20.0)), ), child: ListTile( onTap: (){}, leading: IconButton( icon: Icon(Icons.delete), iconSize: 25.0, color: Colors.white, onPressed: () { setState(() { tasks.removeAt(index); checkValue.removeAt(index); updateValue(); }); }, ), title: Text( '${tasks[index]}', style: TextStyle( fontSize: 18.0, color: Colors.white, fontWeight: FontWeight.bold, decoration: checkValue[index] ? TextDecoration.lineThrough : null, ), ), trailing: Checkbox( value: checkValue[index], activeColor: Colors.white, checkColor: Colors.deepPurple[700], onChanged: (bool value) { setState(() { checkValue[index] = !checkValue[index]; }); }, ), ), ); }, ), ), ),
这样修改后,初始加载时会显示加载指示器,数据加载完成后如果为空会显示友好提示,有数据时正常渲染列表,彻底解决范围错误的问题。
内容的提问来源于stack exchange,提问作者Rishav Naskar
相关产品推荐
相关产品推荐

