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

一、使用软件


DevEco Studio

鸿蒙官方集成开发环境,提供项目管理、代码编辑、模拟器调试、应用打包等全流程开发能力,是 Flutter-OH 应用开发的核心工具。

Flutter-OH SDK


面向 OpenHarmony 生态定制的 Flutter 跨平台开发工具包,支持 Dart 语言编译、鸿蒙平台适配、UI 组件渲染与应用构建


OpenHarmony 模拟器


DevEco Studio 内置的鸿蒙设备虚拟运行环境,无需物理真机即可完成 APP 界面预览、功能调试与兼容性验证。
 

二、核心内容

  1. 重构数据结构,不再单纯保存字符串,升级为笔记对象
  2. 自动生成创建时间、修改时间
  3. 列表只显示简短预览,不全铺长文本
  4. 编辑笔记自动更新修改时间
  5. 完全兼容之前:新增、删除、搜索、本地存储
  6. 适配鸿蒙时间格式,排版更专业

三、操作步骤

步骤 1:升级数据模型(新增笔记实体类)

原本你只能存纯文本,现在要存文本 + 创建时间 + 修改时间 + 收藏状态。在 lib 里面新建文件夹 models,新建文件 note_model.dart写入模型代码(专门存放笔记结构)。

class NoteModel {
  String content;     // 笔记内容
  String createTime;  // 创建时间
  String updateTime;  // 修改时间
  bool isStar;        // 收藏状态

  NoteModel({
    required this.content,
    required this.createTime,
    required this.updateTime,
    this.isStar = false,
  });

  // 转为json(保存本地)
  Map<String,dynamic> toJson(){
    return {
      "content":content,
      "createTime":createTime,
      "updateTime":updateTime,
      "isStar":isStar,
    };
  }

  // 从json读取
  static NoteModel fromJson(Map<String,dynamic> map){
    return NoteModel(
      content: map["content"],
      createTime: map["createTime"],
      updateTime: map["updateTime"],
      isStar: map["isStar"],
    );
  }
}

步骤 2:修改存储工具类 note_storage.dart

之前只能存字符串,现在改成存储笔记对象数组,适配时间保存。全部替换:

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/note_model.dart';

class NoteStorage {
  static const String _key = 'note_list';

  // 保存笔记列表
  static Future<void> saveNotes(List<NoteModel> notes) async {
    final prefs = await SharedPreferences.getInstance();
    List<String> jsonList = notes.map((e)=>jsonEncode(e.toJson())).toList();
    await prefs.setStringList(_key, jsonList);
  }

  // 读取笔记列表
  static Future<List<NoteModel>> loadNotes() async {
    final prefs = await SharedPreferences.getInstance();
    List<String>? strList = prefs.getStringList(_key);
    if(strList==null) return [];
    return strList.map((e)=>NoteModel.fromJson(jsonDecode(e))).toList();
  }
}

步骤 3:编写时间格式化工具(生成当前时间)

打开 utils 新建 time_util.dart

import 'dart:ui';

class TimeUtil{
  // 获取当前时间 年-月-日 时:分
  static String getNowTime(){
    DateTime now = DateTime.now();
    return "${now.year}-${now.month}-${now.day} ${now.hour}:${now.minute}";
  }
}

步骤 4:修改 main.dart 变量

删除旧的 String 列表,替换:

List<NoteModel> _allNotes = [];
List<NoteModel> _showNotes = [];

步骤 5:修改加载方法(读取带时间的笔记)

Future<void> _loadNotes() async {
  final list = await NoteStorage.loadNotes();
  setState(() {
    _allNotes = list;
    _showNotes = List.from(_allNotes);
  });
}

步骤 6:新增笔记时自动生成时间

Future<void> _addNote() async {
  final newText = await Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const MarkdownEditPage()),
  );
  if (newText != null && newText.trim().isNotEmpty) {
    String time = TimeUtil.getNowTime();
    setState(() {
      _allNotes.add(
        NoteModel(
          content: newText,
          createTime: time,
          updateTime: time,
        ),
      );
      _searchNotes();
    });
    await _saveNotes();
  }
}

步骤 7:编辑笔记自动更新修改时间

Future<void> _goEdit(int index) async {
  final realIndex = _allNotes.indexOf(_showNotes[index]);
  final result = await Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => MarkdownEditPage(
        initialContent: _allNotes[realIndex].content,
      ),
    ),
  );
  if (result != null) {
    String newTime = TimeUtil.getNowTime();
    setState(() {
      _allNotes[realIndex].content = result;
      _allNotes[realIndex].updateTime = newTime;
      _searchNotes();
    });
    await _saveNotes();
  }
}

步骤 8:搜索方法改成匹配笔记内容

void _searchNotes() {
  String key = _searchController.text.trim();
  setState(() {
    if (key.isEmpty) {
      _showNotes = List.from(_allNotes);
    } else {
      _showNotes = _allNotes
          .where((note) => note.content.contains(key))
          .toList();
    }
  });
}

步骤 9:列表 UI 升级(显示简短预览 + 时间)

把 ListTile 改成:

ListTile(
  title: Text(
    // 最多显示20个字预览
    _showNotes[index].content.length>20
        ? "${_showNotes[index].content.substring(0,20)}..."
        : _showNotes[index].content,
  ),
  subtitle: Text(
    "创建:${_showNotes[index].createTime}\n修改:${_showNotes[index].updateTime}",
    style: TextStyle(fontSize: 11,color: Colors.grey),
  ),
  onTap: () => _goEdit(index),
  onLongPress: () => _goDelete(index),
),


步骤 10:模拟器运行测试

  • 时间测试:新增笔记自动生成时间,编辑笔记修改时间同步刷新。
  • 预览测试:长文本自动截断加省略号,短文本完整展示。
  • 功能测试:新增、编辑、删除、搜索功能运行正常,无卡顿闪退。
  • 数据测试:重启应用后笔记与时间信息保留,持久化生效。
  • 兼容测试:界面布局适配鸿蒙模拟器,交互流畅无误。

四、总代码

import 'package:flutter/material.dart';
import 'utils/note_storage.dart';
import 'utils/time_util.dart';
import 'pages/markdown_edit_page.dart';
import 'models/note_model.dart';

void main() {
  runApp(const NoteApp());
}

class NoteApp extends StatelessWidget {
  const NoteApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Note App',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<NoteModel> _allNotes = [];
  List<NoteModel> _showNotes = [];
  final TextEditingController _searchController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _loadNotes();
    _searchController.addListener(_searchNotes);
  }

  Future<void> _loadNotes() async {
    final list = await NoteStorage.loadNotes();
    setState(() {
      _allNotes = list;
      _showNotes = List.from(_allNotes);
    });
  }

  Future<void> _saveNotes() async {
    await NoteStorage.saveNotes(_allNotes);
  }

  void _searchNotes() {
    String key = _searchController.text.trim();
    setState(() {
      if (key.isEmpty) {
        _showNotes = List.from(_allNotes);
      } else {
        _showNotes = _allNotes
            .where((note) => note.content.contains(key))
            .toList();
      }
    });
  }

  Future<void> _goEdit(int index) async {
    final realIndex = _allNotes.indexOf(_showNotes[index]);
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => MarkdownEditPage(
          initialContent: _allNotes[realIndex].content,
        ),
      ),
    );
    if (result != null) {
      String newTime = TimeUtil.getNowTime();
      setState(() {
        _allNotes[realIndex].content = result;
        _allNotes[realIndex].updateTime = newTime;
        _searchNotes();
      });
      await _saveNotes();
    }
  }

  Future<void> _goDelete(int index) async {
    final realIndex = _allNotes.indexOf(_showNotes[index]);
    bool? confirm = await showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text("确认删除"),
        content: const Text("确定要删除这条笔记吗?"),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: const Text("取消"),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context, true),
            child: const Text("删除", style: TextStyle(color: Colors.red)),
          ),
        ],
      ),
    );
    if (confirm == true) {
      setState(() {
        _allNotes.removeAt(realIndex);
        _searchNotes();
      });
      await _saveNotes();
    }
  }

  Future<void> _addNote() async {
    final newText = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const MarkdownEditPage()),
    );
    if (newText != null && newText.trim().isNotEmpty) {
      String time = TimeUtil.getNowTime();
      setState(() {
        _allNotes.add(
          NoteModel(
            content: newText,
            createTime: time,
            updateTime: time,
          ),
        );
        _searchNotes();
      });
      await _saveNotes();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("鸿蒙 Note 记事本"),
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(50),
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
            child: TextField(
              controller: _searchController,
              decoration: const InputDecoration(
                hintText: "搜索笔记内容",
                filled: true,
                fillColor: Colors.white,
                border: OutlineInputBorder(),
                prefixIcon: Icon(Icons.search),
              ),
            ),
          ),
        ),
      ),
      body: _showNotes.isEmpty
          ? const Center(
              child: Text(
                "暂无笔记或无搜索结果",
                style: TextStyle(fontSize: 16, color: Colors.grey),
              ),
            )
          : ListView.builder(
              itemCount: _showNotes.length,
              itemBuilder: (context, index) => ListTile(
                title: Text(
                  _showNotes[index].content.length > 20
                      ? "${_showNotes[index].content.substring(0, 20)}..."
                      : _showNotes[index].content,
                ),
                subtitle: Text(
                  "创建:${_showNotes[index].createTime}\n修改:${_showNotes[index].updateTime}",
                  style: TextStyle(fontSize: 11, color: Colors.grey),
                ),
                onTap: () => _goEdit(index),
                onLongPress: () => _goDelete(index),
              ),
            ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addNote,
        child: const Icon(Icons.add),
      ),
    );
  }
}

五、小结---Flutter-OH 鸿蒙工具类应用实战 Day6:笔记时间戳生成与列表预览优化

在标准记事本软件开发流程中,数据结构化优化是项目进阶开发的关键环节。前五篇完成了笔记新增、编辑、删除、搜索与本地存储基础功能,但数据仅以简单字符串格式保存,无法记录笔记生成时间与修改轨迹,不符合正规工具类应用开发规范。本篇对原有数据架构进行重构优化,自定义笔记实体模型,实现自动生成创建时间、实时更新修改时间,同时优化列表预览效果,提升应用专业性与数据完整性。

本次开发首先新建笔记实体模型类,将原本单一文本字段扩充为内容、创建时间、修改时间、收藏状态四大属性,实现笔记数据结构化管理。其次重构本地存储工具,将原本存储字符串列表的逻辑升级为 JSON 对象序列化存储,保证时间信息、编辑记录永久保存,适配持久化需求。同时编写时间工具类,统一格式化输出年月日时分标准时间,贴合鸿蒙系统时间显示规范。

功能逻辑优化方面,新增笔记时系统自动获取当前时间作为创建时间;用户编辑笔记后同步刷新修改时间,精准记录每一次改动轨迹。列表展示层面增加文本截取逻辑,长笔记自动截断并添加省略号,避免页面文字堆砌;同时在笔记下方展示两行时间信息,清晰区分创建与修改记录,布局层次分明、简洁直观。

本次升级完全兼容历史功能,搜索、新增、编辑、删除逻辑不受改动影响,数据无缝迁移。针对边界场景进行调试适配,包括空白笔记过滤、超长文本截取、时间格式错乱防护等优化,保证模拟器运行稳定无报错。

通过本次结构化重构,项目摆脱了简单文本存储模式,具备了正规应用软件的数据模型架构,为后续收藏、分类、标签筛选等高级功能打下坚实基础。本篇优化进一步加深了开发者对 Dart 实体类、JSON 序列化、工具类封装的理解,完成了记事本从简易 demo 向规范化工程项目的进阶升级。

Logo

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

更多推荐