开源鸿蒙 Flutter for OpenHarmony:GetX 实战(笔记列表状态管理)

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

做到 Day7,离线笔记的功能已经不少了:搜索、自动保存、私密笔记、备份导入导出、置顶排序……
这时候很容易出现一个“代码层面”的问题:列表页的刷新逻辑越来越散

  • 搜索框变一下要刷新
  • 导入成功要刷新
  • 编辑页返回要刷新
  • 左滑删除要刷新
  • 置顶/取消置顶要刷新

如果每个地方都 setState(() { future = ... }),短期能跑,长期就会变难维护。
Day8 就把“列表页状态”收拢一下:用第三方库 get(GetX)做一个 NotesController,把加载/防抖/删除/置顶这些行为集中起来,让页面只负责 UI。


1. 今天用到的第三方库:get

GetX 在这篇只用它最常用的 3 个点:

  • Rx:可观察状态(loading / error / notes / keyword)
  • Obx:状态变化自动刷新 UI
  • Get.put / Get.delete:把控制器放到页面生命周期里

添加依赖:

flutter pub add get

2. 先把“状态字段”列清楚

列表页真实需要的状态其实就四个:

  • notes:当前要展示的笔记列表
  • keyword:当前搜索关键字
  • loading:是否正在加载(显示进度条)
  • error:加载失败时的错误信息

把它们放进一个控制器里:

📌 文件:lib/features/note/ui/notes_controller.dart

class NotesController extends GetxController {
  final NoteRepository _repo;

  NotesController(this._repo);

  final notes = <Note>[].obs;
  final keyword = ''.obs;
  final loading = false.obs;
  final error = RxnString();
}

3. 核心:load()(决定到底查 list 还是 search)

列表的加载逻辑只有一条:
关键字为空 → listNotes();有关键字 → searchNotes(keyword)

Future<void> load() async {
  final k = keyword.value.trim();
  loading.value = true;
  error.value = null;
  try {
    final result = k.isEmpty ? await _repo.listNotes() : await _repo.searchNotes(k);
    notes
      ..clear()
      ..addAll(result);
  } catch (e) {
    error.value = '$e';
  } finally {
    loading.value = false;
  }
}

这样页面想刷新时,不需要关心“future 怎么重绑”,只要调用一次 controller.load()


4. 搜索防抖也收拢:onSearchChanged()(停 300ms 再查库)

搜索输入每个字都查库,体验会抖。
做法还是 Day2 那套:防抖 300ms,只是这次把 Timer 放进 Controller,页面更干净。

void onSearchChanged(String text) {
  keyword.value = text.trim();
  _debounce?.cancel();
  _debounce = Timer(const Duration(milliseconds: 300), () {
    load();
  });
}

清空搜索也收拢成一个方法:

Future<void> clearSearch() async {
  keyword.value = '';
  await load();
}

5. 删除 / 置顶:让页面只触发动作,不关心写库细节

页面里最烦的就是“点一下要写库,还要 toast,再刷新”。
这些非常适合收进 Controller。

5.1 删除

Future<void> delete(Note note) async {
  final id = note.id;
  if (id == null) return;
  try {
    await _repo.delete(id);
    await showToast('已删除');
  } catch (e) {
    await showToast('删除失败:$e');
  }
  await load();
}

5.2 置顶/取消置顶

Future<void> togglePinned(Note note) async {
  final id = note.id;
  if (id == null) return;
  final next = !note.pinned;
  try {
    await _repo.setPinned(id: id, pinned: next);
    await showToast(next ? '已置顶' : '已取消置顶');
  } catch (e) {
    await showToast('操作失败:$e');
  }
  await load();
}

6. 页面改造:FutureBuilder → Obx

📌 文件:lib/features/note/ui/notes_list_page.dart

6.1 初始化 Controller(Get.put)

final db = AppDatabase.instance;
_repo = NoteRepository(NoteDao(db), NoteCrypto(db));
_controller = Get.put(NotesController(_repo));

页面销毁时删掉控制器(Get.delete):


void dispose() {
  Get.delete<NotesController>();
  _searchController.dispose();
  super.dispose();
}

6.2 用 Obx 渲染三种状态:loading / error / list

Expanded(
  child: Obx(() {
    if (_controller.loading.value) {
      return const Center(child: CircularProgressIndicator());
    }
    final err = _controller.error.value;
    if (err != null) {
      return Center(child: Text('加载失败:$err'));
    }

    final notes = _controller.notes;
    if (notes.isEmpty) {
      final keyword = _controller.keyword.value.trim();
      if (keyword.isEmpty) return const Center(child: Text('暂无笔记,点右下角新增'));
      return Center(child: Text('未找到与「$keyword」相关的笔记'));
    }

    return ListView.separated(
      itemCount: notes.length,
      separatorBuilder: (_, __) => const Divider(height: 1),
      itemBuilder: (_, index) {
        final note = notes[index];
        ...
      },
    );
  }),
)

6.3 页面事件全部变成“调用控制器方法”

  • 搜索框:onChanged: _controller.onSearchChanged
  • 清空:_controller.clearSearch()
  • 刷新:onPressed: _controller.load
  • 删除:onDismissed: (_) => _controller.delete(note)
  • 置顶:onPressed: () => _controller.togglePinned(note)

到这里,页面就很像“纯 UI 组件”,业务动作集中在 Controller。


📷
在这里插入图片描述
在这里插入图片描述

7. 自测清单(Day8)

  • 搜索输入:连续输入/删除字符,列表能跟着变化(防抖生效)
  • 导入备份成功:返回列表自动刷新
  • 编辑笔记返回:列表自动刷新
  • 左滑删除:toast 正常 + 列表刷新
  • 点星标:toast 正常 + 列表重新排序

Logo

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

更多推荐