You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的不同状态(加载中、错误、无数据)。

  • 修复步骤:

    1. 处理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,
              );
            }
          },
        ),
      )
      
    2. 优化LoadData函数:getTaskList()本身返回Future,不需要用async包裹,修改为:

      void LoadData() {
        taskList = dbHelper!.getTaskList();
      }
      
    3. 额外建议:如果DBHelper的getTaskList()可能返回null,建议修改该方法返回Future<List<TaskModel>>而非Future<List<TaskModel>?>,确保始终返回非空列表(空列表而非null),进一步避免空安全问题。

内容的提问来源于stack exchange,提问作者DANISH MOBIYA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:20:37