继续完善项目,把未完善的功能和页面继续开发完成。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

完善页面

1、消息页「添加会话」

问题描述

  • 页面lib/pages/messages_page.dart — 消息页 AppBar 右侧「添加会话」图标按钮。
  • 原行为:点击后仅弹出 SnackBar:「添加会话功能开发中」。

关键代码(修复前)

// lib/pages/messages_page.dart(约 84-91 行,修复前)
actions: [
  IconButton(
    icon: appUserPlusIcon(size: 24),
    onPressed: () {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('添加会话功能开发中')),
      );
    },
  ),
],
  • 点击「添加会话」改为打开新建会话弹窗:输入会话名称 → 确认后向列表头部插入一条新会话,并给出「已添加会话:xxx」的 SnackBar,不再出现「待开发中」。
  • 新增方法:
    • _showAddConversationDialog(BuildContext context):弹出 AlertDialog,内含 TextField 与取消/添加按钮。
    • _submitAddConversation(BuildContext dialogContext, TextEditingController controller):校验非空、生成 idsetState 插入 ConversationModel、关闭弹窗并显示 SnackBar。

关键代码位置

  • 按钮绑定:lib/pages/messages_page.dart 中 AppBar actionsIconButtononPressed: () => _showAddConversationDialog(context)
  • 弹窗与提交逻辑:同文件内 _showAddConversationDialog_submitAddConversation 方法(在 _openChat 之后)。

2. 我的 — 设置页内三项

  • 页面lib/pages/profile_page.dart → 由「设置」进入的二级设置页。
  • 入口:设置页 ListView 中的三个 ListTile:「通知设置」「隐私与安全」「清除缓存」。
  • 当前行为:点击后仅通过 _showSnackOn(settingsContext, msg) 显示与项同名的 SnackBar(如「通知设置」「隐私与安全」「已清除缓存」),无实际持久化或系统设置/清理逻辑。

关键代码

// lib/pages/profile_page.dart 约 84-99 行
ListTile(
  title: const Text('通知设置'),
  trailing: appChevronRightIcon(size: 22, interactive: false),
  onTap: () => _showSnackOn(settingsContext, '通知设置'),
),
ListTile(
  title: const Text('隐私与安全'),
  ...
  onTap: () => _showSnackOn(settingsContext, '隐私与安全'),
),
ListTile(
  title: const Text('清除缓存'),
  ...
  onTap: () => _showSnackOn(settingsContext, '已清除缓存'),
),
// lib/pages/profile_page.dart 约 111-113 行
void _showSnackOn(BuildContext scaffoldContext, String msg) {
  ScaffoldMessenger.of(scaffoldContext).showSnackBar(SnackBar(content: Text(msg)));
}

建议完善方向:通知设置 → 持久化开关 + 系统通知权限;隐私与安全 → 隐私政策/权限说明页;清除缓存 → 调用图片/临时文件清理并刷新统计。


3. 发布页 — 发布按钮

  • 页面lib/pages/upload_page.dart
  • 当前行为:表单校验通过后延迟 1 秒,然后显示 SnackBar「发布成功(模拟)」并清空标题/描述,无真实上传 API。

关键代码

// lib/pages/upload_page.dart 约 16-24 行
Future<void> _mockUpload() async {
  if (!_formKey.currentState!.validate()) return;
  setState(() => _uploading = true);
  await Future.delayed(const Duration(seconds: 1));
  setState(() => _uploading = false);
  ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('发布成功(模拟)')));
  _title.clear();
  _desc.clear();
}

这个项目没有后端,后端接口就暂时不做,后续可以对接实际上传接口,成功后提示改为「发布成功」并可选跳转首页/个人页。


4. 我的 — 退出登录

  • 页面lib/pages/profile_page.dart
  • 当前行为:弹窗确认后仅执行 _showSnack('已退出登录'),未清除登录态或跳转登录页。

关键代码

// lib/pages/profile_page.dart 约 155-176 行
void _logout() {
  showDialog<void>(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text('退出登录'),
      content: const Text('确定要退出当前账号吗?'),
      actions: [
        ...
        FilledButton(
          onPressed: () {
            Navigator.of(context).pop();
            _showSnack('已退出登录');
          },
          child: const Text('退出'),
        ),
      ],
    ),
  );
}

建议完善方向:清除本地 token/用户信息、调用登出 API(若有)、并跳转至登录页或重置为未登录状态。


以上修改后运行发现了下面的报错,报错截图如下
在这里插入图片描述

二、报错处理:添加会话弹窗关闭时 _dependents.isEmpty 断言失败

  • 界面:整屏红底,Flutter 调试态断言失败 overlay。
  • 来源package:flutter/src/widgets/framework.dart,约 line 6079 pos 14。
  • 断言内容'_dependents.isEmpty': is not true.
  • 含义:框架期望某对象在此时没有依赖者(_dependents 为空),但实际仍有依赖。常见于控件/元素正在被移除或 dispose 时,仍有子节点或监听方在引用它。

复现

在消息页点击「添加会话」→ 在弹窗中输入名称并点击「添加」(或取消关闭弹窗)后,弹窗关闭时触发上述断言。

原因分析

新建会话弹窗中使用了 TextEditingController,并在 showDialog(...).then((_) => controller.dispose()) 里在 dialog 的 Future 完成时立即 dispose 了 controller。

  • showDialog 的 Future 在 Navigator.pop() 被调用时即完成。
  • 此时弹窗的 widget 树可能仍在当前帧内拆解,TextField 仍持有对 controller 的依赖。
  • 立即 controller.dispose() 会在「仍有 dependents」的情况下销毁 controller,触发框架内部 _dependents.isEmpty 的断言。

在这里插入图片描述

处理步骤与关键代码

  1. 问题定位:确认断言来自 framework.dart_dependents.isEmpty,并结合最近改动锁定为「添加会话」弹窗关闭时的 TextEditingController.dispose() 时机。
  2. 修复思路:不在 dialog 关闭的同一时刻 dispose controller,而是延后到下一帧再 dispose,确保弹窗树已完全移除、TextField 不再依赖该 controller。
  3. 代码修改lib/pages/messages_page.dart_showAddConversationDialog 方法末尾):

修改前:

).then((_) => controller.dispose());

修改后:

).then((_) {
  // 延后到下一帧再 dispose,避免弹窗树尚未完全移除时 TextField 仍依赖 controller 导致 _dependents.isEmpty 断言失败
  WidgetsBinding.instance.addPostFrameCallback((_) {
    controller.dispose();
  });
});
  1. 验证:再次在消息页打开「添加会话」→ 输入并点击「添加」或点击「取消」关闭弹窗,确认红屏断言不再出现,且新会话列表与 SnackBar 行为正常。

小结

项目 说明
报错类型 Flutter 断言失败 _dependents.isEmpty(framework.dart)
触发位置 消息页「添加会话」弹窗关闭时
根本原因 在 dialog 的 Future 完成时立即 dispose TextEditingController,此时 TextField 仍为依赖方
修复方式 .then 中使用 WidgetsBinding.instance.addPostFrameCallbackcontroller.dispose() 推迟到下一帧执行
相关文件 lib/pages/messages_page.dart_showAddConversationDialog

结束语

感谢阅读本帖,如对贴中内容有意见和建议的,欢迎与我联系交流,也欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐