Flutter:获取数据库数据后创建AlertDialog并动态修改容器颜色
解决Flutter AlertDialog异步数据更新容器颜色的问题
核心问题在于你直接在Container的color参数中调用异步函数setCompletedTasksColor——这个函数返回的是Future<bool>而非即时的布尔值,初始判断时会把Future对象和true比较(结果永远为false),且异步完成后不会自动触发UI更新。
下面提供两种可行的解决方案:
方案一:提前获取所有数据再弹出Dialog
先批量获取所有需要的任务状态,等数据全部准备完毕后再创建并弹出AlertDialog,确保Dialog一开始就显示正确的颜色。
示例代码:
// 定义弹出Dialog的函数,先预加载数据 Future<void> showTaskStatusDialog(String selectedSimName) async { // 替换成实际的月份数量 final int monthCount = 12; List<bool> taskStatusList = []; // 批量获取每个月份的任务完成状态 for (int i = 0; i < monthCount; i++) { bool status = await setCompletedTasksColor(selectedSimName, i); taskStatusList.add(status); } // 数据加载完成后,再构建并弹出Dialog showDialog( context: context, builder: (context) { final size = MediaQuery.of(context).size; return AlertDialog( content: SizedBox( height: size.height * 0.1, child: Row( children: List.generate(monthCount, (index) { return Expanded( child: Container( height: size.height * 0.05, width: size.width * 0.16, decoration: BoxDecoration( color: taskStatusList[index] ? Colors.green : kSelectedMenuColorLavender, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(10.0), bottomRight: Radius.circular(10.0), ), ), child: Center(child: Text(getQtgMonths(index), textAlign: TextAlign.center)), ), ); }), ), ), ); }, ); } // 优化后的状态获取函数(避免返回null,类型更安全) Future<bool> setCompletedTasksColor(String selectedTask, int index) async { var response = await fetchSelectedTasks(selectedTask, getQuarter(index)); // 用类型判断替代runtimeType,更可靠 if (response is Map) { var taskStatus = response['taskCompleted']; return taskStatus == 'true'; } else { return false; } }
方案二:用FutureBuilder包裹动态组件
如果不想让用户等待所有数据加载完成再看Dialog,可以给每个需要动态颜色的Container套上FutureBuilder,让组件自己处理异步加载逻辑,加载过程中可以保留默认颜色或显示占位状态。
示例代码:
// AlertDialog内的组件修改为: Expanded( child: FutureBuilder<bool>( future: setCompletedTasksColor(selectedSimName, index), initialData: false, // 默认颜色对应的状态 builder: (context, snapshot) { // 异步完成后获取状态,默认false bool isCompleted = snapshot.data ?? false; final size = MediaQuery.of(context).size; return Container( height: size.height * 0.05, width: size.width * 0.16, decoration: BoxDecoration( color: isCompleted ? Colors.green : kSelectedMenuColorLavender, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(10.0), bottomRight: Radius.circular(10.0), ), ), child: Center(child: Text(getQtgMonths(index), textAlign: TextAlign.center)), ); }, ), ), // 同样优化状态获取函数 Future<bool> setCompletedTasksColor(String selectedTask, int index) async { var response = await fetchSelectedTasks(selectedTask, getQuarter(index)); if (response is Map) { var taskStatus = response['taskCompleted']; return taskStatus == 'true'; } else { return false; } }
两种方案对比:
- 方案一适合数据量小的场景,用户不会看到颜色跳动,体验更流畅;
- 方案二适合数据量大或需要快速弹出Dialog的场景,组件会逐个更新颜色。
内容的提问来源于stack exchange,提问作者Itis Me
相关产品推荐
相关产品推荐

