GetX控制器late变量初始化报错:页面加载红屏问题求助
解决方案
问题根源
late Map<String, double> dataMap1仅声明未初始化实例,异步加载完成前直接访问会触发未初始化错误;reportFunction中调用dataMap1.addAll()时,dataMap1本身是null,会导致空指针;- 异步加载数据期间,UI直接渲染依赖未就绪的
dataMap1,引发红屏。
方案一:使用GetX响应式变量(推荐)
修改控制器代码
import 'package:get/get.dart'; import 'package:hive/hive.dart'; class ReportScreenController extends GetxController{ // 用RxMap创建响应式Map,初始化为空Map final RxMap<String, double> dataMap1 = <String, double>{}.obs; final Map<String, double> dataMap2 = { "ورزشی": 5, "خصوصی": 3, "اداری": 5, "دسته بندی نشده": 3, }; @override Future<void> onInit() async { super.onInit(); await reportFunction(); } Future<void> reportFunction() async { var taskBox = await Hive.openBox('task'); var taskFinish = taskBox.values.where((task) => task.status == true).toList(); var taskUnFinish = taskBox.values.where((task) => task.status == false).toList(); double finishedCount = taskFinish.length.toDouble(); double unFinishedCount = taskUnFinish.length.toDouble(); // 直接赋值给响应式Map,自动通知UI更新 dataMap1.value = { 'رو زمین مانده': unFinishedCount, 'تکمیل شده': finishedCount, }; } }
修改视图代码
用Obx包裹依赖dataMap1的组件,监听数据变化,数据就绪后自动渲染:
class ReportScreen extends GetView<ReportScreenController> { const ReportScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Stack( fit: StackFit.expand, children: [ background(), Padding( padding: const EdgeInsets.symmetric(horizontal: 15.0), child: Column( children: [ const Text(':نمودار فعالیت', style: boldText), // 用Obx监听dataMap1变化,数据为空时显示加载组件 Obx(() { if (controller.dataMap1.isEmpty) { return const CircularProgressIndicator(); // 加载中提示 } return MyPieChart(dataMap: controller.dataMap1); }), const Text(':نمودار وظایف', style: boldText), MyPieChart(dataMap: controller.dataMap2), ], ), ), ], ), ); } }
方案二:使用普通Map+手动更新UI
如果不想用响应式变量,也可以初始化dataMap1为空Map,加载完成后调用update()通知UI刷新:
修改控制器代码
import 'package:get/get.dart'; import 'package:hive/hive.dart'; class ReportScreenController extends GetxController{ // 初始化空Map,无需late Map<String, double> dataMap1 = {}; final Map<String, double> dataMap2 = { "ورزشی": 5, "خصوصی": 3, "اداری": 5, "دسته بندی نشده": 3, }; @override Future<void> onInit() async { super.onInit(); await reportFunction(); update(); // 数据加载完成后通知UI更新 } Future<void> reportFunction() async { var taskBox = await Hive.openBox('task'); var taskFinish = taskBox.values.where((task) => task.status == true).toList(); var taskUnFinish = taskBox.values.where((task) => task.status == false).toList(); double finishedCount = taskFinish.length.toDouble(); double unFinishedCount = taskUnFinish.length.toDouble(); dataMap1 = { 'رو زمین مانده': unFinishedCount, 'تکمیل شده': finishedCount, }; } }
修改视图代码
用GetBuilder包裹组件,监听控制器的更新:
class ReportScreen extends GetView<ReportScreenController> { const ReportScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Stack( fit: StackFit.expand, children: [ background(), Padding( padding: const EdgeInsets.symmetric(horizontal: 15.0), child: Column( children: [ const Text(':نمودار فعالیت', style: boldText), GetBuilder<ReportScreenController>( builder: (ctrl) { if (ctrl.dataMap1.isEmpty) { return const CircularProgressIndicator(); } return MyPieChart(dataMap: ctrl.dataMap1); }, ), const Text(':نمودار وظایف', style: boldText), MyPieChart(dataMap: controller.dataMap2), ], ), ), ], ), ); } }
额外优化点
- 避免
double.parse(taskFinish.length.toString())这种冗余写法,直接用taskFinish.length.toDouble()更简洁; - 可以给
MyPieChart添加空数据判断,防止传入空Map时出错; - 异步操作建议添加异常捕获,避免加载失败时崩溃:
Future<void> reportFunction() async { try { var taskBox = await Hive.openBox('task'); // ... 原有逻辑 } catch (e) { print('加载数据失败: $e'); // 可以设置默认数据 dataMap1.value = {'خطا': 1}; } }
内容的提问来源于stack exchange,提问作者sadegh
相关产品推荐
相关产品推荐

