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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 13:06:24