Flutter SQLite任务管理器FutureBuilder空检查错误排查求助
解决FutureBuilder中"Null check operator used on a null value"错误
我正在开发一款基于SQLite的任务管理器App,通过函数加载数据后使用FutureBuilder组件展示,但代码触发空检查错误,提示“Null check operator used on a null value”。
问题代码
import 'package:flutter/material.dart'; import 'package:smart_task/database/db_handler.dart'; import 'package:smart_task/models/task_model.dart'; import 'profile.dart'; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { DBHelper? dbHelper; late Future<List<TaskModel>> taskList; var _currentIndex = 0; DateTime now = DateTime.now(); @override void initState() { super.initState(); dbHelper = DBHelper(); LoadData(); } LoadData() async { taskList = dbHelper!.getTaskList(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.brown[400], appBar: AppBar(title: Text('Smart Task')), body: Column( children: [ Expanded( child: FutureBuilder( future: taskList, builder:(context, AsyncSnapshot<List<TaskModel>> snapshot) { return ListView.builder(itemBuilder: (context, index) { return Card( child: ListTile( title: Text(snapshot.data![index].title.toString()), subtitle: Text(snapshot.data![index].dateAndTime.toString()), ), ); }, itemCount: snapshot.data!.length, ); }, ), ) ], ), bottomNavigationBar: BottomNavigationBar( items: const [ BottomNavigationBarItem( icon: Icon(Icons.home), label: 'Task', tooltip: 'List of Task'), BottomNavigationBarItem( icon: Icon(Icons.person), label: 'Profile', tooltip: 'Profile') ], currentIndex: _currentIndex, onTap: (value) { setState(() { _currentIndex = value; }); }, ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButton: FloatingActionButton( elevation: 10, onPressed: () async { // dbHelper! // .insert(TaskModel( // title: 'task', // description: 'this is my first sqlite operation', // dateAndTime: // '${now.day}-${now.month}-${now.year}-${now.hour}:${now.minute}:${now.second}', // status: false, // taskPoints: 0)) // .then((value) { // print('added successfully task'); // }).onError((error, stackTrace) { // print(error); // }); }, tooltip: 'Add New Task', child: const Icon(Icons.add), ), ); } }
报错栈信息
======== Exception caught by widgets library ======================================================= The following _CastError was thrown building FutureBuilder<List<TaskModel>>(dirty, state: _FutureBuilderState<List<TaskModel>>#c3881): Null check operator used on a null value The relevant error-causing widget was: FutureBuilder<List<TaskModel>> FutureBuilder:file:///B:/Flutter%20Development/smart_task/lib/screen/home.dart:38:22 When the exception was thrown, this was the stack: #0 _HomeState.build.<anonymous closure> (package:smart_task/screen/home.dart:49:49) #1 _FutureBuilderState.build (package:flutter/src/widgets/async.dart:616:55) #2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4992:27) #3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4878:15) #4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11) #5 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5) #6 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2667:19) #7 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21) #8 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5) #9 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15) #10 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9) #11 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5) #12 _invoke (dart:ui/hooks.dart:148:13) #13 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5) #14 _drawFrame (dart:ui/hooks.dart:115:31) ====================================================================================================
问题原因与修复方案
问题根源:FutureBuilder在异步任务未完成、数据返回null或请求失败时,
snapshot.data会是null,代码中直接用!强制非空访问,触发空检查错误。同时代码未处理snapshot的不同状态(加载中、错误、无数据)。修复步骤:
处理FutureBuilder的各种状态:在builder函数中依次判断状态,避免直接访问null数据:
Expanded( child: FutureBuilder( future: taskList, builder: (context, AsyncSnapshot<List<TaskModel>> snapshot) { // 加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return Center(child: CircularProgressIndicator()); } // 请求错误状态 else if (snapshot.hasError) { return Center(child: Text('加载失败:${snapshot.error}')); } // 无数据状态 else if (!snapshot.hasData || snapshot.data!.isEmpty) { return Center(child: Text('暂无任务数据')); } // 数据正常返回状态 else { return ListView.builder( itemBuilder: (context, index) { return Card( child: ListTile( title: Text(snapshot.data![index].title.toString()), subtitle: Text(snapshot.data![index].dateAndTime.toString()), ), ); }, itemCount: snapshot.data!.length, ); } }, ), )优化LoadData函数:
getTaskList()本身返回Future,不需要用async包裹,修改为:void LoadData() { taskList = dbHelper!.getTaskList(); }额外建议:如果
DBHelper的getTaskList()可能返回null,建议修改该方法返回Future<List<TaskModel>>而非Future<List<TaskModel>?>,确保始终返回非空列表(空列表而非null),进一步避免空安全问题。
内容的提问来源于stack exchange,提问作者DANISH MOBIYA
相关产品推荐
相关产品推荐

