尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【听见课堂 HarmonyOS NEXT 实战系列 03】ArkUI 页面为什么不该直接操作数据库:Service 与 Repository 分层实战
【听见课堂 HarmonyOS NEXT 实战系列 03】ArkUI 页面为什么不该直接操作数据库Service 与 Repository 分层实战在 ArkUI 项目中直接在页面生命周期里打开数据库、查询列表、筛选结果再顺手更新计数看起来是最快的实现方式。问题是一旦课程首页、复习页、任务中心和历史记录都需要同一批数据页面就会逐渐拥有多套不同的业务口径。听见课堂采用ArkUI Page → Service → Repository → RelationalStore的分层方式。页面负责展示和交互草稿态Service 负责业务规则与聚合Repository 负责数据源读写。下面结合项目中的真实接口拆解这条数据链路。一、页面直接查库会带来什么问题假设复习页需要展示“待确认字幕”和“待确认扫描”任务中心需要展示“今天到期”“已逾期”“已完成”。如果每个页面都直接查询数据库很快会出现这些问题页面重复拼装查询条件字段口径容易不一致保存任务后要手工更新多个页面的角标与统计数字数据库异常、空库和迁移失败被迫在 UI 中处理单元测试必须创建页面和系统上下文难以隔离业务规则未来切换内存数据、测试数据或远程数据时页面需要大面积修改。更稳妥的做法是让页面只知道“我要一个复习快照”或“我要更新这条任务”而不关心底层使用了哪张表。二、Repository 用接口隔离数据源听见课堂首先定义ClassroomRepository接口把课程、字幕、扫描和任务的读写动作集中起来exportinterfaceClassroomRepository{getTodayCourse():PromiseCourseSummary;getTranscript():PromiseArrayTranscriptSegment;replaceTranscript(courseId:string,transcript:ArrayTranscriptSegment):Promiseboolean;getScanNotes():PromiseArrayScanNote;getTasks():PromiseArrayTaskItem;updateCourse(course:CourseSummary):Promiseboolean;updateScanText(scanId:string,text:string,source?:string):Promiseboolean;updateTask(taskId:string,title:string,dueText:string,dueAtMillis:number):Promiseboolean;confirmTask(taskId:string):Promiseboolean;setTaskCompleted(taskId:string,completed:boolean):Promiseboolean;}接口的价值不只是“面向接口编程”。它明确了数据层的职责边界Repository 返回领域模型不返回页面组件需要的临时颜色、按钮文案或弹窗状态。项目同时可以拥有RelationalClassroomRepository和内存实现。前者用于真实本地数据后者可以作为能力不可用时的降级或测试替身。上层 Service 不需要知道当前使用的是哪种实现。三、Service 负责业务聚合不只是转发调用如果 Service 只是把 Repository 的方法原样包一层分层并没有产生真正价值。听见课堂在 Service 中完成确认状态筛选、任务统计和能力状态归一化。例如任务中心需要的内容可以一次聚合为页面快照asyncgetTaskCenterSnapshot():PromiseTaskCenterSnapshot{consttasks:ArrayTaskItemawaitthis.repository.getTasks();constnowMillis:numberDate.now();constitems:ArrayTaskCenterItemtasks.filter((task:TaskItem)task.confirmed).map((task:TaskItem):TaskCenterItem{constdueAtMillistask.dueAtMillis0?task.dueAtMillis:TaskDateResolver.resolveDueText(task.dueText,nowMillis);constoverdueTaskDateResolver.isOverdue(dueAtMillis,task.completed,nowMillis);conststatustask.completed?已完成:(overdue?已过期:待办);returnnewTaskCenterItem(task.id,task.title,task.dueText,task.source,status,TaskDateResolver.dateGroup(dueAtMillis,nowMillis),task.completed,overdue,,dueAtMillis,TaskDateResolver.dateKey(dueAtMillis));});// 后续统一排序并计算 pending、completed、overdue 与日历统计}任务中心也可以由 Service 统一计算“今日”“逾期”“已完成”等分组。这样手机底部导航角标、平板侧栏统计和任务中心列表都基于同一份 canonical data而不是在三个页面中各自加减计数。一个重要原则是写入完成后重新读取并聚合权威数据不要手工猜测其他页面应该变成什么状态。四、初始化逻辑应该只有一个入口应用启动时EntryAbility调用统一初始化方法而不是自己创建数据库exportasyncfunctioninitializeClassroomData(context:common.UIAbilityContext):Promiseboolean{try{constrepositorynewRelationalClassroomRepository();awaitrepository.initialize(context);classroomService.useRepository(repository,RelationalStore);returntrue;}catch(error){classroomService.useRepository(fallbackRepository,内存降级);returnfalse;}}具体实现可以先尝试创建 RelationalStore Repository失败时切换到内存实现并记录原因。对页面而言只要 Service 注册完成它就能通过稳定接口加载数据。这也让失败路径更容易解释初始化成功页面加载本地持久化数据数据库不可用但降级成功页面仍可操作但应提示数据不会持久保存Service 未初始化页面进入明确错误态提供重试而不是一直显示 loading。五、页面只负责消费状态和触发动作在页面层推荐把一次刷新写成清晰的状态转换privateasyncrefreshData():Promisevoid{this.isDataLoadingtrue;this.dataError;try{this.courseawaitthis.service.getTodayCourse();this.transcriptawaitthis.service.getTranscript();this.scanNotesawaitthis.service.getScanNotes();this.candidateTasksawaitthis.service.getCandidateTasks();this.confirmedTasksawaitthis.service.getConfirmedTasks();this.reviewSnapshotawaitthis.service.getReviewSnapshot();this.taskCenterSnapshotawaitthis.service.getTaskCenterSnapshot();}catch(error){this.dataError课堂数据暂时不可用请稍后重试。;}finally{this.isDataLoadingfalse;}}页面仍然需要处理loading、empty、error、disabled和pressed但它不负责解释数据库错误码也不负责决定什么叫“待确认”。当用户确认一段字幕时页面触发 Service 动作动作完成后重新请求复习快照。即使另一个页面或后台流程修改了数据页面也会回到 Repository 中的真实结果。六、RelationalStore 负责结构化数据与迁移字幕、扫描、任务都具备列表、筛选、排序和关联关系适合使用 RelationalStore。Repository 实现需要额外关注首次安装时建表与种子数据schema 版本升级与迁移空库、重复主键和脏数据兜底多步写入时的事务一致性将数据库行映射回显式 ArkTS 类型异常转换成上层可理解的错误而不是直接把底层对象抛给页面。用户设置、主题开关或少量最近状态则更适合 Preferences。不要因为 Preferences 调用简单就把任务列表序列化成一个越来越大的字符串。七、分层之后如何测试这套结构可以把验证拆开Repository 测试验证建表、增删改查、排序和迁移Service 测试注入内存 Repository验证确认筛选、任务统计和边界日期页面测试验证加载、空态、错误态和交互反馈真机验证验证 RelationalStore、生命周期恢复和数据持久化。构建成功只能说明类型、资源和打包链路基本成立不能替代数据库迁移测试单元测试通过也不能替代真机生命周期验证。发布文章时同样要如实区分这些证据层级。总结Page → Service → Repository不是为了增加文件数量而是为了让每一层只回答一种问题页面决定怎么显示Service 决定业务规则Repository 决定数据如何读写。下一篇将继续向下看领域数据本身分析Course、Transcript、Scan和Task如何组成一条可追溯的课堂证据链。
RELATED

相关推荐

STM32驱动ADS1110实现16位高精度ADC采集完整指南

STM32驱动ADS1110实现16位高精度ADC采集完整指南

简介:本资源是一套面向STM32初学者与嵌入式开发者的ADS1110高精度ADC驱动实战代码包,专为解决IC接口16位模数转换芯片在STM32平台上的快速集成与稳定采样问题而设计,适用于传感器数据采集、工业测控及教学实验等场景。压缩包共151个文件&…

📅 2026/11/5 21:43:37
社交产品测试工程师笔试复盘:核心考点与实战思路

社交产品测试工程师笔试复盘:核心考点与实战思路

1. 当一份测试笔试摆在你面前,先别急着刷题最近不少朋友在准备大厂测试岗的秋招,聊到一个很有意思的题目——“搜狐2018秋招第二批-社交中心-测试工程师试卷”。虽然年份看起来有点久,但说真的,这类老试卷里藏着的东西&#xff0c…

📅 2026/9/9 13:57:54
测试(5) - 概念篇(3)-- 常见的测试模型

测试(5) - 概念篇(3)-- 常见的测试模型

测试模型: 文章目录测试模型:1. V模型:优点缺点2. W模型:核心特点优点:缺点:3. 总结如果你是第一次看这篇博客,可以看一看我之前关于 软件测试–概念篇 的博客介绍:测试(3) - 概念篇…

📅 2026/9/7 23:58:41
MORE NEWS

更多资讯

📰

高压电工证查询20天 上岗必备怎么准备最稳妥

高压电工证查询20天 上岗必备怎么准备最稳妥 你是不是也担心学历不高报不了高压电工证?别急,今天就来聊聊高压电工证查询20天怎么安排,特别是对于那些想在南阳卧龙区中小施工企业找工作的朋友,这真的是 上岗必备 的硬门槛。…

📰

考低压电工证时间限制证全国通用吗

低压电工证实操怕挂科?2026河南最新政策说清楚 实操考试心里没底怕挂科?2026河南最新政策说清楚,考低压电工证时间限制你得知道。…

📰

新低压电工证好考吗 你在外省考的证怎么报名转过来

新低压电工证好考吗 你在外省考的证怎么报名转过来 之前考的证在外省能不能转过来?这个问题几乎每个特种作业从业者都会遇到,尤其是像你这样在许昌公路工程从业,常年奔波在不同项目之间的人。新低压电工证好考吗?怎么报名?这些问题不仅影响你能否顺利上…

📰

考低压电工证时间限制培训机构怎么选

低压电工证时间限制有啥讲究?学历不高也能上岗必备! 你是不是也担心学历不高,考低压电工证时间限制太严格,根本报不上名?别急,下面这些干货,帮你搞清楚低压电工证到底怎么考,哪些时间点必须盯紧,哪怕学历低也照样能拿到【上岗必备】的证书。…

📰

电工证到哪里去考试 良心建议别走弯路

电工证到哪里去考试 良心建议别走弯路 实操考试心里没底怕挂科,这事儿谁没经历过?我认识的老李,就是个典型例子。他是个南阳的建筑工人,平时干的都是低压电工活儿,但一直没考电工证,心里一直发虚,怕哪天被查到被罚款。直到上个月,工地来了个检查组,…

📰

哪家发的电工证好通过率揭秘:周口劳务班组负责人必看的电工证办理全攻略

哪家发的电工证好通过率揭秘:周口劳务班组负责人必看的电工证办理全攻略 怕考不过白交培训费?你不是一个人。现在不少劳务班组的负责人,在考虑要不要报电工证的时候,都面临着这个选择难题: 哪家发的电工证好 ?更关键的是, 通过率揭秘…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬