用 ArkTS 做好分布式通知管理:从核心 API 到可验证交互
用 ArkTS 做好分布式通知管理:从核心 API 到可验证交互
开篇:先看清页面实际做了什么
页面标题是“分布式通知管理”,界面提供手机发布通知、同步策略和隐私模式三个区域。需要先说明:“同步到平板和手表”只是页面反馈文字,当前应用没有设备发现、网络通信、数据库或系统通知中心调用。文章只解释页面中能够直接看到的状态和交互,不把文案扩大成真实设备通信。

一、页面整体结构
页面没有生命周期操作,也没有异步初始化;三个状态变量在页面创建时直接赋值,因此首次进入时会显示固定的默认状态。
最外层是 Scroll,内容是一个垂直 Column({ space: 16 })。根列宽度为 100%,内边距为 18,根容器高度为 100%,背景色是 #F4FAFD。Scroll 的作用是允许整个内容在窗口变窄或字体放大后上下滚动;它不代表通知数据已经分页,更不等同于懒加载。根列中依次放置介绍卡片、发布卡片和策略卡片。
介绍卡片内部再次使用 Column,间距为 6。第一行文本是 26 号加粗深蓝标题,第二行是 14 号辅助说明。卡片宽度铺满,内边距 20,圆角 20,背景淡蓝色。发布卡片包含小标题、按钮行和反馈文本。按钮行使用 Row,间距 10;两个 Button 都设置 layoutWeight(1),因此平分行宽。策略卡片则包含三行策略、Toggle 和一行解释文字。
这种结构有两个优点:第一,组件层次与视觉分组一致,读源码时能够从外到内找到每个区域;第二,布局参数集中在对应容器上,后续调整卡片间距不会影响按钮内部。页面没有使用自定义 Builder,所有内容都写在 build 中,适合展示一个较小的单页示例。
二、状态模型:policy、privacy 与 notice
页面有三个状态:
@State policy: string = '仅重要'
@State privacy: boolean = true
@State notice: string = '暂无待同步通知'
policy 是同步策略,允许值来自 private policies: string[] = ['全量同步','仅重要','关闭同步']。初始策略为“仅重要”,所以用户刚打开页面时,普通微信消息不会被视为可同步,系统更新则会同步。privacy 是隐私模式布尔值,初始为 true。它只影响反馈中显示“仅显示摘要”还是“显示详情”,并不保存真正的摘要内容。notice 是反馈区域的文本,默认提示暂无通知,按钮触发后被替换为当前结果。
@State 的关键意义是让界面由状态计算得到。策略行的背景和勾选符号读取 policy,Toggle 读取 privacy,说明文字和反馈区域读取 privacy、notice。当回调修改状态时,ArkUI 会重新计算依赖这些变量的声明式表达式,不需要手动刷新页面。状态职责清晰也减少了重复数据:页面没有另外保存 selectedIndex,也没有保存一份与 privacy 相同的说明字符串。
状态初始化还体现了演示页面与生产页面的差异。当前值是写死的,重新进入页面会回到默认状态;如果实际产品要求记住策略,需要使用持久化能力并处理读取失败、首次安装和版本升级。文档不能因为有一个名为 policy 的变量,就声称工程已经接入系统策略中心。
三、publish 方法与分支顺序
publish(title: string, important: boolean) 接收通知标题和重要性。微信按钮传入 publish('微信消息', false),系统更新按钮传入 publish('系统更新', true)。方法先判断关闭同步,再判断“仅重要”下的普通通知,最后处理允许同步的情况:
if (this.policy === '关闭同步') {
this.notice = '同步已关闭:通知仅保留在手机'
} else if (this.policy === '仅重要' && !important) {
this.notice = '普通通知未同步,符合“仅重要”策略'
} else {
this.notice = title + ' 已同步到平板和手表' +
(this.privacy ? '(仅显示摘要)' : '(显示详情)')
}
分支顺序不能随意交换。关闭同步是最高优先级,即使通知重要,也必须停留在手机;因此它放在最前面。第二个条件同时检查策略和重要性,只有当前策略为“仅重要”且消息普通时才成立。全量同步下普通消息会进入最后分支,仅重要下重要消息也会进入最后分支。最后一段根据隐私开关追加文案,开关打开显示摘要,关闭显示详情。
这个方法是同步函数,执行过程中没有网络等待,也不会抛出服务错误。所谓发布成功只是更新 notice。真实分布式通知需要把这里替换成权限检查、设备选择、消息构造、发送调用和结果回调,并增加 loading、success、error 等状态。当前代码没有这些逻辑,测试也只能验证文本结果。
四、按钮事件与可观察反馈
两个按钮颜色不同,但颜色只是视觉区分,不表示一个按钮权限更高。按钮宽度通过 layoutWeight 平分,触摸区域覆盖整块按钮。onClick 使用箭头函数捕获当前组件实例,调用 publish 并传入固定参数。按钮点击后 notice 会立即变化,用户可以在卡片中的浅灰蓝区域看到结果。
验证按钮时要覆盖多种组合。初始“仅重要+隐私开启”点击微信,应显示普通通知未同步;点击系统更新,应显示“系统更新 已同步到平板和手表(仅显示摘要)”。切换全量同步后点击微信,应显示同步成功;切换关闭同步后点击任一按钮,都应显示“同步已关闭:通知仅保留在手机”。切换隐私关闭后,只有进入成功分支时才会出现“显示详情”;被策略拦截的普通消息不会附加该词,因为代码直接设置了另一条 notice。
反馈文本没有单独的错误样式,也没有 Toast、Dialog 或日志记录。它是页面内的最后一次结果,下一次点击会覆盖上一次内容。若要保留历史通知,需增加数组状态和列表组件,但那会改变当前示例的职责,不能在文章里当作现成功能描述。
五、ForEach 策略行
策略数组是普通成员,不是 @State,因为当前页面不会在运行时增删策略。ForEach 读取数组并为每个字符串生成 Row。左侧 Text 展示名称,layoutWeight(1) 占据剩余空间;右侧 Text 在选中时展示“✓”,未选中时为空字符串。Row 设置宽度 100%、内边距 12、圆角 10,并绑定 onClick,将 item 赋值给 policy。
点击任意一行后,旧行的背景回到 #F9FBFC,旧行勾选清空,新行背景变为 #E8F5FF 并显示勾选。这个变化来自同一个 policy 状态,而不是代码里逐行修改样式。对于固定的三个选项,使用字符串比较足够直观;如果选项数量增加,建议使用带 id 的对象并给 ForEach 提供稳定 key,避免文本改名导致业务条件失效。
列表行没有使用 Radio 组件,所以它不是系统级单选控件;它只是用基础 Row、Text 和条件样式组合出的单选视觉。无障碍语义、键盘焦点和自动化测试标识都没有额外配置。生产化时可以补充可访问性文本,让读屏器读出当前策略及可点击状态。
六、Toggle 的读取和回写
Toggle 指定 ToggleType.Switch,isOn 读取 privacy。用户拖动或点击开关时,onChange 回调得到布尔值并写回 this.privacy。开关下方的 Text 使用三元表达式同步显示两种说明。打开状态文案为“隐私模式:其他设备只显示通知摘要”,关闭状态文案为“详情模式:同步通知完整内容”。
这里的摘要和详情仅存在于文字层。源码没有消息正文,也没有字段筛选、加密或跨设备传输,所以不能把 Toggle 当成隐私保护实现。它展示的是设置项如何影响展示结果。若要扩展,真正的消息对象应在发送前根据 privacy 生成不同 payload,接收端也应重新检查权限;同时要明确用户关闭隐私后可能泄露哪些字段,并给出确认或风险提示。
Toggle 没有持久化。页面重新创建后 privacy 仍为 true,策略也回到“仅重要”。这是最容易在演示与产品之间产生误解的地方。测试时应专门退出页面再进入,确认状态是否按预期重置;若产品需求是保持选择,则需要另行设计存储层,不能仅把 @State 改成其他装饰器。
七、视觉、尺寸与响应式观察
根背景 #F4FAFD 提供轻微蓝色,三张白色卡片形成层次。标题使用 #173F5F,说明使用 #55758C 和 #627D98,颜色对比足以区分主次。卡片的圆角与内边距统一,发布区和策略区都使用 18 的内边距,介绍区稍大,为 20。页面没有阴影和图片,渲染成本低,适合在模拟器中快速观察。
Row 的 layoutWeight 让两个按钮在不同宽度下保持等宽。如果改用固定宽度,窄屏可能换行或溢出;当前实现只设置 100% 宽度,未指定最小宽度,因此在极窄窗口仍需实际测试。Scroll 可以承接垂直方向的内容增长,但 Column 没有设置横向滚动,长标题应依靠 Text 自动换行。反馈 Text 设置 lineHeight 20,长文案会增加高度,不会覆盖按钮。
页面没有深色模式资源、横屏专属布局或平板双栏布局。标题写着平板和手表只属于通知文案,不代表页面已经针对这些设备适配。文章中提到响应式时,应限定为“当前宽度和高度约束下的基础伸缩”,不能推断出完整多设备适配策略。
八、源码事实与扩展边界
当前已经实现:三个 @State 状态;三种策略的本地选择;两个模拟通知按钮;根据策略和重要性计算提示;隐私开关改变提示文字;Scroll、Column、Row、Text、Button、Toggle、ForEach 的组合布局。当前没有实现:真实通知发布、设备发现、跨设备连接、远端确认、消息队列、权限申请、历史记录、持久化、网络异常处理、加密和撤回。
如果把它扩展成真实功能,第一步应定义通知数据模型,例如标题、正文、重要等级、创建时间和目标设备。第二步检查系统通知权限及用户对跨设备流转的授权。第三步根据 policy 和 privacy 过滤消息,再调用平台能力发送。第四步为发送中、成功、失败、设备离线和超时建立明确状态。最后把这些状态映射到当前 notice 区域或独立列表。扩展过程中仍可保留现有组件树,先替换 publish,再逐步增加状态,不必一次重写页面。
九、DevEco Studio 验证清单
启动页面后,确认初始策略为仅重要、隐私开关打开、提示为暂无待同步通知。逐个点击三条策略,观察背景色和勾选是否唯一;分别在三种策略下点击微信消息和系统更新,观察提示文字;打开和关闭隐私开关后重复成功路径,比较摘要与详情文字。改变窗口宽度和系统字体,观察页面滚动、按钮排列和文字换行。重新进入页面,确认状态恢复初始值。
出现异常时先看状态赋值而不是猜测分布式服务。策略不变通常是点击回调没有执行或 item 值拼写不一致;Toggle 文案不变通常是 privacy 没有在 onChange 中回写;按钮无反馈则检查 publish 参数和 notice 赋值。由于工程没有异步 API,构建通过后所有交互都应立即可见。
十、结语
这个示例的重点是用少量、职责明确的状态描述一个通知设置页。policy 决定是否允许同步,privacy 决定提示中展示摘要还是详情,notice 记录最后一次操作结果。ForEach 负责把固定策略数组渲染成可点击行,Button 和 Toggle 通过事件改变状态,ArkUI 自动更新依赖它们的界面。理解这条数据流,比记住某个组件的参数更重要。
当你把它用于真实 HarmonyOS 应用时,请继续保持同样的边界意识:页面文案不是系统能力,状态开关不是安全机制,Scroll 不是数据懒加载。先验证当前页面,再逐步接入权限、设备和传输服务,才能让分布式通知从可点击的原型变成可靠、可解释的产品。
运行结果回顾
- 启动页面显示标题、副标题、发布区和策略区。
- 初始 policy 为“仅重要”,privacy 为 true,notice 为“暂无待同步通知”。
- 三条策略可点击且始终只有一条显示勾选。
- 微信消息在仅重要策略下被拦截,系统更新可以同步。
- 全量同步允许两种消息,关闭同步阻止两种消息。
- 隐私开关改变成功消息中的摘要/详情文案。
- 页面内容在窄窗口和大字号下可通过 Scroll 查看。
- 重新进入页面后状态恢复源码中的默认值。
- 页面中的演示字符串不等于真实跨设备 API 调用。
十七、学习者可以怎样修改而不破坏现有行为
如果要做小实验,建议一次只改一个变量。先把默认 policy 改成“全量同步”,运行后观察初始勾选和微信消息结果;再恢复默认值,给 policies 增加一个临时选项,观察它会进入 publish 的哪一条分支;最后把按钮标题改成另一种通知名称,确认 title 只影响成功提示。这些实验可以帮助理解数据如何从声明、事件传参一路流向 Text,而不会引入外部服务的不确定性。
也可以只调整布局参数:把根列的 space 从 16 改成 8,比较卡片密度;把按钮 Row 的 space 改成 4,观察按钮间距;把反馈文本字号调大,检查 Scroll 的滚动效果。修改时应保留功能代码不变,并逐项记录视觉差异。若把多个属性同时改动,出现问题后很难判断是哪一个约束造成的。对于初学者,这种小步实验比直接复制一套复杂的生产模板更容易建立对 ArkUI 的直觉。
十八、最终认识
这个页面没有假装解决所有分布式问题,它把一个复杂概念压缩成几个可操作的本地状态。用户选择策略,应用根据重要性决定是否允许;用户选择隐私模式,应用在允许同步时改变展示说明;用户点击通知按钮,页面把结果放回固定反馈区域。每条路径都能在运行页面中复现,每个显示结果都能回到对应的状态表达式。
当你能准确解释这些细节时,才算真正读懂了这个工程。之后无论接入系统通知、分布式数据对象还是自建服务,都可以沿用同一套方法:先定义状态,再明确事件,再处理成功和失败,最后让 UI 从状态自然生成。本文的价值就在于把“分布式通知管理”这个标题还原成一份可核对的 ArkTS 页面,而不是堆砌与工程无关的术语。
十一、把一次点击还原成完整数据流
阅读这个页面时,可以把用户的一次点击拆成四个阶段。第一阶段是输入,用户点击某一行策略、按钮或 Toggle;第二阶段是事件回调,ArkUI 将点击事件交给 onClick 或 onChange;第三阶段是状态写入,回调修改 policy、privacy 或 notice;第四阶段是声明式重算,依赖状态的 Text、Row 和 Toggle 重新得到属性。这个流程没有手动查找控件,也没有命令式地设置某个 Text 的内容。对初学者来说,最值得练习的是在纸上画出“谁读取哪个状态、谁修改哪个状态”,一旦关系画清楚,界面行为就不再神秘。
例如点击“关闭同步”这一行,只有 policy 发生变化,privacy 和 notice 不会变化。因为策略行的背景和勾选依赖 policy,所以三行会重新计算;Toggle 和说明依赖 privacy,理论上不需要改变;反馈区域依赖 notice,也会继续显示之前的内容。随后点击系统更新,publish 读取最新 policy,第一分支成立,再把 notice 改成关闭提示。这个顺序说明设置变化不会自动执行发布,发布动作仍由按钮触发。若产品希望切换策略时立即清空旧提示,就需要在策略行的 onClick 中显式处理 notice,但当前源码没有这样做。
再看隐私开关。开关回调只写 privacy,不会改变 notice,因此用户切换后,旧的成功消息可能仍显示“仅显示摘要”。只有下一次进入成功分支时,publish 才会读取新的 privacy 并生成详情文案。这种行为是源码决定的,不应被文章擅自解释为 bug 或安全策略。若要让反馈实时反映设置,应该在需求层明确切换时是否刷新历史提示,然后再修改代码。
十二、为什么使用字符串而不是数字索引
策略数组和 policy 都使用中文字符串,这让页面代码非常直观。ForEach 回调拿到“全量同步”“仅重要”或“关闭同步”,比较表达式一眼就能读懂。对于只有三个固定选项的教学示例,这种方式降低了额外类型声明的负担。但字符串也有风险:文案一旦改成“仅同步重要通知”,publish 中的比较条件如果没有同步修改,就会出现界面选中但逻辑不匹配的情况。
可演进的做法是定义策略对象,例如每项包含 id、label 和允许普通消息的布尔值,UI 使用 label,业务使用 id。这样翻译文案或调整显示风格不会影响判断。文章不把这种对象写进当前工程,因为源码里没有它;这里只说明从现有实现出发的改造思路。无论采用字符串还是对象,必须保证列表显示值和 publish 能识别的值来自同一处定义,避免维护两份列表。
十三、窗口、字体和触摸测试的细节
验证页面时不要只在默认预览尺寸下截图。把窗口拖窄,观察两个按钮是否仍保持可读文字;把系统字体调大,观察标题、副标题和反馈区域是否换行;连续切换策略并点击按钮,确认文字不会溢出卡片。Scroll 只负责纵向承载,如果某一行的内容在极端宽度下横向超出,仍需从 Text 的宽度和换行属性排查。当前标题和三条策略都较短,正常设备上不会出现明显问题,但测试这些边界可以帮助理解布局约束。
触摸测试应点击整行的空白区域,而不只点击文字。如果整行都能切换策略,说明 onClick 绑定在 Row 上,当前代码正是如此。按钮则应检查按下反馈和连续快速点击,虽然 publish 是同步函数,不会产生并发请求,但连续点击会连续覆盖 notice。若将来接入异步发送,就必须增加防重复提交或请求序列号,避免较早请求的结果覆盖较新操作。
十四、从演示反馈到真实错误处理
当前 notice 是单一字符串,适合让学习者看到结果,却无法区分成功、拦截和异常。真实应用通常需要一个状态模型,例如 idle、sending、success、blocked、failed,并为每种状态准备用户能理解的文案。策略拦截属于业务结果,不应显示成网络错误;设备离线属于环境错误,应提示用户稍后重试;权限拒绝则应引导用户到设置页面。把错误分类后,UI 才能提供正确的下一步操作。
异步 publish 还会引入生命周期问题。用户离开页面后请求返回,组件是否仍然存在?多个设备同时发送时,哪一条结果应该显示?这些问题不能靠拼接字符串解决。可以在组件销毁时取消请求,或在结果回调中确认页面仍处于活动状态;可以给每次发送分配 id,只展示最近一次操作的结果。这些设计属于接入真实服务时的工作,不应误写成当前示例已经具备的能力。
十五、可维护性检查
当前页面把状态、业务方法和全部布局放在一个组件中,结构短小,阅读路径直接。随着功能增加,可以把策略卡片提取为子组件,通过 @Prop 接收当前策略和回调;把发布按钮抽成可复用的 Builder,传入标题、颜色和重要性;把反馈区域单独封装,统一处理不同状态的颜色。拆分的目标是减少页面构建复杂度,而不是为了展示更多抽象层。对于只有三个卡片的页面,过早拆分反而会增加理解成本。
颜色和间距目前直接写在链式调用中,便于初学者对照运行效果。多人协作或多页面复用时,可以建立常量或主题资源,统一卡片圆角、主色和辅助色。无论是否抽取,都要确保视觉改变不会悄悄改变交互含义,例如不能仅因为颜色变灰就让用户误以为策略被禁用,除非同时修改可点击状态。
十六、页面行为回顾
页面由 Scroll、Column、Row、Text、Button、Toggle 和 ForEach 组成。它有三个状态、三条策略、两个通知按钮和四类反馈结果;没有 Builder、LazyForEach 或网络请求。运行时应观察初始值、策略名称、按钮传入的通知类型和提示文字,图片只用于辅助理解页面外观。
独立阅读这张页面时,只需要知道它的目标是展示通知策略、隐私开关和反馈结果。前文解释页面目的,中段拆开状态和交互,后文说明可观察边界。每个判断都应落到某个状态、组件属性或页面结果上,不能用“提升体验”之类的空泛句子代替实际行为。
十九、从页面结构理解状态
面对这张页面,最有效的学习方式是先列出三个状态,再把策略行、通知按钮和隐私开关分别对应到它们。策略列表是只读候选数据,页面不会在运行时增加策略;通知按钮把标题和重要性传给发布逻辑;反馈区域读取最后一次提示。这样可以从可见内容理解数据如何流动,而不需要先记住入口文件名称。
这种顺序可以避免被标题误导。标题中的“分布式”容易让人联想到设备管理和网络协议,但源码真正给出的事实是一个本地决策器:输入是策略、隐私开关、通知名称和重要性,输出是一句提示。把输入输出写成表格后,四条核心路径一目了然。关闭同步会拦截一切;仅重要会拦截普通消息;全量同步允许两类消息;允许的消息还要根据 privacy 选择摘要或详情。文章中的每个结论都应该能回到这张逻辑表,而不是依靠概念联想。
在 ArkTS 中,链式属性调用经常让初学者误以为每一行都是独立命令。实际上 Text、Button、Row 等组件先被创建,再通过 fontSize、width、padding、backgroundColor 等属性描述外观和约束,最后通过 onClick 或 onChange 注册事件。组件树在 build 执行时由这些声明组成,状态变化后框架重新计算受影响的部分。理解“描述结果”而不是“逐句操作控件”,有助于解释为什么代码里看不到 setText 或 invalidate 一类调用。
二十、四种业务组合的人工测试记录
为了让验证可复现,可以固定一套操作顺序。启动后先确认 policy 为仅重要、privacy 为开、notice 为暂无待同步通知。点击微信消息,反馈应变为普通通知未同步,符合“仅重要”策略。此时再点击系统更新,反馈应变为系统更新已同步到平板和手表(仅显示摘要)。这两次点击验证了同一策略下 important 参数的差异,也说明 notice 只保留最后一次操作。
接着点击全量同步行,观察蓝色背景和勾选移动到第一行。点击微信消息,普通通知现在进入成功分支,反馈显示微信消息已同步到平板和手表(仅显示摘要)。关闭隐私开关,再点击系统更新,反馈中的括号应变成显示详情。注意切换开关本身不会改写旧 notice,只有下一次成功发布才读取新的 privacy,这一点要在记录中注明。
最后选择关闭同步,分别点击微信消息和系统更新。两次结果都应是同步已关闭:通知仅保留在手机,且不会出现摘要或详情后缀。这组测试证明关闭同步判断位于 publish 的第一分支,而不是只针对普通通知。完成后重新点击仅重要,确认勾选只恢复到一行,旧提示不会因为策略改变而自动清空。这样一组测试覆盖了策略、重要性、隐私和覆盖式反馈四个维度。
如果测试结果与预期不同,应先记录当前三项状态,再对照分支条件。比如全量同步下微信仍被拦截,可能是 policy 字符串前后有空格;关闭同步下系统更新显示成功,则应检查第一项比较是否被误改。不要直接增加一个新的 if 来“修正”截图,因为那可能掩盖状态来源问题。教学工程的价值正在于每个结果都可以从少量代码推导出来。
二十一、状态重建与页面生命周期
@State 解决的是组件存活期间的刷新,不等同于永久保存。当前页面没有 onPageShow、onPageHide 或其他生命周期逻辑,也没有从 Preferences、数据库或文件读取值。只要组件重新创建,三个初始值就再次生效。测试时可通过返回上一级再进入页面观察这一点;如果宿主没有销毁页面,也可能暂时保留实例,这是运行环境的导航行为,不应写成应用拥有持久化能力。
真实产品若需要跨启动记住同步策略,要先决定保存什么。policy 是三个受控字符串,适合保存标识;privacy 是布尔值,适合保存开关状态;notice 只是瞬时反馈,通常不应在下次启动时恢复为“上次发送结果”。读取持久化数据时还要处理旧版本保存了未知策略、用户清理数据和读取失败等情况。本文不修改这些内容,因为当前工程的教学目标是状态绑定和分支反馈。
页面重建还提醒我们不要把状态复制到多个变量。例如当前策略行直接比较 this.policy,发布方法也直接读取 this.policy,没有另一个 selectedPolicy。若同时维护两个值,就可能出现勾选显示“全量同步”而 publish 仍按“仅重要”判断的短暂不一致。保持单一事实来源是这份小页面易于理解的重要原因。
二十二、组件约束的实际含义
根 Scroll、根 Column 和三张卡片都设置 width(‘100%’),外层又设置 padding(18)。这表示卡片希望占满可用内容宽度,但内容区的实际边界要扣除父容器内边距。卡片自身再设置 padding,文字和按钮不会贴住边缘。若把某个 width 改成固定值,必须重新观察窄窗口;若去掉父 Column 的 padding,卡片会贴近屏幕边缘,视觉层级随之变化。
Row 中两个 Button 使用 layoutWeight(1),权重相同,所以剩余空间被平均分配。按钮文字长度不同并不会改变分配比例,微信消息和系统更新仍保持相同宽度。策略 Row 的 Text 使用 layoutWeight(1),右侧勾选文本只占自身需要的宽度,因而勾选始终靠右。这个差异很适合用来理解“权重占剩余空间”和“自然尺寸”之间的区别。
卡片 Column 使用 space(10) 或 space(6),它只影响子组件之间的间隔,不会代替 padding。圆角通过 borderRadius 设置,背景色通过 backgroundColor 设置,二者共同形成卡片效果。页面没有 Shadow、Image 或自定义绘制,因此布局问题主要来自尺寸和文本换行,而不是复杂渲染。调试时可以临时给 Row 加不同背景色观察边界,确认后再恢复源码中的颜色。
二十三、文案与业务判断的耦合
本工程把策略的显示文案同时当作判断值。这样写省去了映射,但也把界面语言和业务逻辑绑在了一起。中文文章中经常把“仅重要”改写成“仅同步重要通知”,若读者照着文章修改界面而不修改 publish,就会得到一个看似选中、实际不生效的选项。维护时应把这种风险明确写入代码评审清单。
另一处耦合是按钮标题直接作为 publish 的 title 参数。按钮改名后,成功反馈也会跟着改名,因为方法并不知道这是微信还是系统更新,只接收一段文字和一个布尔值。这种设计适合演示少量固定动作;当按钮代表复杂对象时,应传递明确的数据结构,再由显示层决定文案。当前不需要为两个按钮引入额外模型,但读者可以通过这一点理解参数设计的取舍。
隐私文案同样是展示层表达。privacy 为 true 时只拼接“仅显示摘要”,并没有真实摘要字段。若未来加入消息正文,必须把“界面写了摘要”与“传输内容经过筛选”分成两个可验证步骤。只有在发送载荷、接收渲染和日志记录都遵循同一规则时,隐私模式才具有产品意义。当前页面不具备这些条件,因此文章始终把它称作演示开关。
二十四、从单字符串反馈到可观察界面
notice 的默认值和三种结果都使用 String,优点是实现直接、截图容易对照;缺点是界面无法知道结果类别。比如“普通通知未同步”和“同步已关闭”都只是普通文本,颜色没有区分,读屏器也只能读出句子。若要在不改变核心逻辑的前提下增强可读性,可以增加一个 status 字段,在 publish 的每个分支同时设置 status 和 notice,再由 Text 的 fontColor 根据 status 选择颜色。
这属于合理扩展,但不能倒推为现有实现。扩展时还要考虑状态是否会残留:用户从失败状态切换策略后,是否立即显示新的建议,还是等待下一次发布?如果增加重试按钮,重试应复用上一次的 title 和 important,这又要求保存最近请求。每增加一个可见行为,都应明确它由哪个状态驱动,避免在事件回调里直接散落多处文案。
在当前版本中,覆盖式反馈反而能让数据流足够简单。读者只需观察最后一次点击后的文字,不必判断历史列表顺序。这个简化是教学边界,而不是产品缺陷;只有需求明确要求查看历史,才需要引入数组、ForEach 列表和清理策略。
二十五、面向读者的练习路径
初学者可以先不改代码,使用开发者工具在关键回调处观察 policy、privacy 和 notice 的值。然后复制一份工程进行实验:为 policies 增加“仅本机”选项,但暂时不改 publish,运行并记录点击后为什么总会落入最后分支;再把 publish 的判断补齐,比较修改前后的结果。这个练习能直观看到 UI 选项和业务分支必须共同维护。
第二个练习是把 notice 的 lineHeight 从 20 改为 28,给出一条较长的自定义 title,观察文本高度和 Scroll 行为。第三个练习是在 Button 回调中先切换 privacy 再调用 publish,确认同一次点击读取的是最新值。实验结束后应恢复示例源码,避免把个人练习结果误当成工程现状。
如果后续要学习真实分布式能力,可以把页面继续当作输入和反馈层:它负责收集 policy、privacy 和通知输入,服务层再负责权限、设备和发送结果,并通过明确的回调把状态交回页面。当前示例的策略分支和隐私文案仍然可以作为界面验证基础,但真实服务的连接、失败和超时不属于当前实现。
二十八、按通知类型理解页面反馈
微信消息和系统更新并不是两个独立页面,而是同一发布区域中的两种输入。微信消息传入普通通知标记,系统更新传入重要通知标记;策略决定是否继续,隐私开关只在允许继续后影响摘要或详情。把这两个按钮放在同一张卡片里,读者可以直接比较同一策略下普通和重要通知的差异。
例如初始的“仅重要”策略会拦截微信消息,但允许系统更新;切换到“全量同步”后,两种消息都进入成功反馈;切换到“关闭同步”后,两种消息都停留在手机。隐私模式打开时,成功反馈带有“仅显示摘要”,关闭时改为“显示详情”。这六种组合都来自当前页面实际存在的三个状态和两个按钮,足以构成完整的交互说明。
二十六、页面图片与可见结果
初始图、操作图和代码图分别帮助读者理解默认状态、一次按钮反馈和页面结构。插图只能说明画面中可见的标题、策略、按钮和提示,不能证明设备真的收到通知,也不能把图片文字当成系统通知中心记录。
阅读图片时,可以重点比较颜色、选中行和反馈文案;代码图只作辅助,不能代替页面行为本身。即使暂时不看图片,读者也应能根据前面的状态和操作说明理解页面。
二十七、总结性复盘
从这份工程可以提炼出一条很具体的 ArkUI 复盘路径:先找入口,确认组件树;再列状态,确认每个状态的初值和读取位置;随后追踪事件,确认回调写入哪些状态;最后按所有条件组合运行页面,检查可见反馈。这个路径不依赖“分布式”或“通知”等大词,换成任何本地设置页面也同样适用。
当前代码最宝贵的地方是边界清楚。它用 policy 模拟同步决策,用 privacy 模拟展示选择,用 notice 模拟操作反馈,却没有把字符串拼接冒充系统服务。读者既能看到完整的交互闭环,又能知道真实产品还缺哪些层。按这种方式阅读和写作,文章会更长,但长度来自可核对的状态、组件和验证,而不是重复口号。
更多推荐




所有评论(0)