当前位置: 首页 > news >正文

HarmonyOS 启动模式实战:singleton、multiton 与 specified 怎么选?

文章目录

    • 前言
    • 一、三种启动模式概述
      • 1.1 启动模式是什么?
      • 1.2 三种启动模式对比
    • 二、启动模式的配置方法
      • 2.1 在 module.json5 中配置
      • 2.2 launchType 相关属性说明
    • 三、指定实例模式(specified):自定义实例分发
      • 3.1 为什么需要指定实例?
      • 3.2 实现步骤
      • 3.3 启动指定实例 Ability
    • 四、三种模式的适用场景分析
      • 4.1 如何选择启动模式?
      • 4.2 场景对比速查表
    • 五、启动模式与 Want 参数
      • 5.1 什么是 Want?
      • 5.2 Want 核心属性说明
      • 5.3 如何传递参数并在目标 Ability 中接收?
    • 总结
      • 三种模式核心速查
      • 3 个关键结论

前言

想象一下,你管理着一家连锁餐厅。现在有三种经营策略:

  • 策略 A:全国只开一家旗舰店,所有客人来都去这一家。这叫单实例(singleton)。
  • 策略 B:每座城市开一家分店,客人各去各城市的店。这叫多实例(multiton)。
  • 策略 C:根据客人的会员等级决定去哪家店——同一个 VIP 客人始终去固定那家,不同 VIP 去不同的店。这叫指定实例(specified)。

在 HarmonyOS 中,UIAbility 的启动模式(LaunchType)就是这套"经营策略"。选对启动模式,能让应用既省资源又体验流畅。本文将结合源码,讲清楚三种模式的行为差异、配置方法和适用场景。

一、三种启动模式概述

1.1 启动模式是什么?

在 HarmonyOS 中,UIAbility是应用的基本组件单元。当你从桌面点击图标、点击通知、扫码打开应用时,系统需要决定"如何启动这个 Ability"——是每次都创建新的,还是复用已有的?启动模式就是这个决策规则。

1.2 三种启动模式对比

启动模式配置值行为描述典型适用场景
单实例模式singleton全局只存在一个实例,再次启动时触发onNewWant而非onCreate应用主页、设置页
多实例模式multiton每次启动都创建新实例,各实例互相独立文档编辑器、多文件查看
指定实例模式specified由开发者通过AbilityStage.onAcceptWant自定义分发规则聊天会话、订单详情页

一句话总结singleton无论启动多少次只有一个实例;multiton每次启动都产生新实例;specified由开发者决定——同一个标识复用已有实例,不同标识创建新实例。


二、启动模式的配置方法

2.1 在 module.json5 中配置

每个UIAbility都在module.json5中声明自己的启动模式,通过launchType字段指定:

{"module":{"abilities":[{"name":"EntryAbility","srcEntry":"./ets/entryability/EntryAbility.ets","description":"$string:EntryAbility_desc","icon":"$media:icon","label":"$string:EntryAbility_label","startWindowIcon":"$media:icon","startWindowBackground":"$color:start_window_background","launchType":"singleton"},{"name":"WorkAbility","srcEntry":"./ets/workability/WorkAbility.ets","description":"$string:WorkAbility_desc","icon":"$media:icon","label":"$string:WorkAbility_label","startWindowIcon":"$media:icon","startWindowBackground":"$color:start_window_background","launchType":"multiton"},{"name":"SessionAbility","srcEntry":"./ets/sessionability/SessionAbility.ets","description":"$string:SessionAbility_desc","icon":"$media:icon","label":"$string:SessionAbility_label","startWindowIcon":"$media:icon","startWindowBackground":"$color:start_window_background","launchType":"specified"}]}}
  • "launchType": "singleton":单实例,应用内只会有一个该 Ability 实例。
  • "launchType": "multiton":多实例,每次调用startAbility()都会创建新实例。
  • "launchType": "specified":指定实例,需配合AbilityStage.onAcceptWant()自定义分发规则。

注意module.json5是标准 JSON 格式,不支持注释。实际使用时请删除所有注释行。

2.2 launchType 相关属性说明

属性名类型必填说明
launchTypestringAbility 启动模式,取值:singleton/multiton/specified
srcEntrystringAbility 对应的 ArkTS 源码路径
namestringAbility 的唯一名称,全应用内不可重复
descriptionstringAbility 的描述信息

三、指定实例模式(specified):自定义实例分发

3.1 为什么需要指定实例?

大白话理解:微信聊天列表里,每打开一个聊天窗口(比如和"张三"的聊天),微信不会每次都新建一个进程,而是根据聊天对象决定:和张三聊就复用"张三聊天窗口",和李四聊就创建一个新窗口。

这种"根据业务标识决定是否复用"的场景,就是specified模式的用武之地。

3.2 实现步骤

specified模式需要两步配合:

第一步:在module.json5中将目标 Ability 的launchType设为specified

{"abilities":[{"name":"ChatAbility","srcEntry":"./ets/chatability/ChatAbility.ets","launchType":"specified"}]}

第二步:在AbilityStage中重写onAcceptWant回调,定义实例分发规则:

// AbilityStage.etsimport{AbilityStage,Want}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';constTAG='ChatAbilityStage';constDOMAIN=0x0000;exportdefaultclassChatAbilityStageextendsAbilityStage{/** * 当 launchType 为 specified 的 Ability 被启动时,系统调用此方法, * 询问开发者:应该使用哪个实例? * 返回值作为实例标识:相同标识复用已有实例(触发 onNewWant), * 不同标识创建新实例(触发 onCreate)。 */onAcceptWant(want:Want):string{hilog.info(DOMAIN,TAG,'ChatAbilityStage onAcceptWant');// 从 want.parameters 中提取业务标识(如会话ID、订单号等)constsessionId=want.parameters?.sessionIdasstring;if(sessionId){// 返回含 sessionId 的字符串作为实例标识return`ChatAbility_${sessionId}`;}// 没有 sessionId 时,返回默认标识(所有未指定会话共用一个实例)return'ChatAbility_default';}}

要点说明

  • onAcceptWant仅在specified模式的 Ability 被启动时触发,其他模式不会调用。
  • want.parameters中提取业务标识(会话 ID、订单号等),返回值决定实例的唯一性
  • 返回相同字符串 → 复用已有实例(触发onNewWant);返回不同字符串 → 创建新实例(触发onCreate)。
  • 返回值格式由开发者自行定义,但同一业务实体必须始终返回相同的字符串,否则会创建重复实例。

3.3 启动指定实例 Ability

import{common,Want}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';constDOMAIN=0x0000;// 从 UIAbility 的 context 发起启动letcontext=this.getUIContext().getHostContext()ascommon.UIAbilityContext;// 构建 Want,parameters 中带上业务标识letwant:Want={deviceId:'',// 空字符串表示本设备bundleName:'com.example.myapp',abilityName:'ChatAbility',parameters:{sessionId:'user_12345_chat_001'// 业务标识,决定是否复用实例}};// 启动 ChatAbilitycontext.startAbility(want).then(()=>{hilog.info(DOMAIN,'testTag','启动聊天窗口成功');}).catch((err:Error)=>{hilog.error(DOMAIN,'testTag','启动失败: %{public}s',JSON.stringify(err));});

四、三种模式的适用场景分析

4.1 如何选择启动模式?

核心判断逻辑:

  1. 不需要多个实例→ 选singleton(绝大多数页面)
  2. 需要多个实例,由用户主动创建→ 选multiton(如文档编辑器)
  3. 需要多个实例,由业务数据驱动→ 选specified(如聊天会话、订单详情)

4.2 场景对比速查表

业务场景推荐模式理由
应用主页(首页)singleton全局唯一,复用更省资源
设置页singleton无需多开
视频播放器singleton同时只需一个播放实例
文档编辑器(多文档)multiton用户主动同时打开多份文档
文件管理器(多窗口)multiton每个文件对应独立窗口
社交应用聊天窗口specified每个会话对应固定实例
购物应用订单详情specified每个订单对应固定实例
邮件阅读页specified每封邮件对应固定实例

五、启动模式与 Want 参数

5.1 什么是 Want?

在 HarmonyOS 中,Want是一个"启动意图"对象,类似于一张"任务卡"——上面写着要执行什么操作(action)、要启动哪个 Ability(abilityName)、要传递什么数据(parameters)。

letwant:Want={deviceId:'device_001',// 目标设备 ID(本设备填空字符串)bundleName:'com.example.myapp',// 目标应用包名abilityName:'DetailAbility',// 目标 Ability 名称action:'action.detail',// 操作类型(可选)uri:'http://example.com',// 数据 URI(可选)parameters:{// 传递给 Ability 的自定义参数id:'12345',from:'home'}};

5.2 Want 核心属性说明

属性名类型说明示例值
deviceIdstring目标设备 ID,空字符串表示本设备''
bundleNamestring目标应用的包名'com.example.app'
abilityNamestring目标 Ability 的名称'DetailAbility'
actionstring操作类型(可选)'ohos.want.action.viewData'
uristring数据 URI(可选)'http://example.com'
parametersobject自定义参数,传递给目标 Ability{ id: '123' }

5.3 如何传递参数并在目标 Ability 中接收?

// ——— 发起方:启动 Ability 并传递参数 ———letwant:Want={bundleName:'com.example.myapp',abilityName:'DetailAbility',parameters:{productId:'PROD_001',// 商品 IDfrom:'recommendation',// 来源页面extraData:{// 嵌套数据对象discount:0.8,userId:'U10086'}}};context.startAbility(want).then(()=>{hilog.info(DOMAIN,'testTag','启动成功');});// ——— 接收方:在 DetailAbility 的 onCreate / onNewWant 中读取参数 ———onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{constproductId=want.parameters?.productIdasstring;constfrom=want.parameters?.fromasstring;constextraData=want.parameters?.extraDataasRecord<string,Object>;hilog.info(DOMAIN,'testTag',`productId=${productId}, from=${from}`);}

提示want.parameters中的值类型为Object,读取时需要手动类型断言(as stringas number等)。建议在接收方做类型校验,避免因参数缺失导致运行时报错。


总结

三种模式核心速查

模式实例数量再次启动的回调需要额外配置
singleton全局唯一onNewWant
multiton每次新建onCreate
specified按标识决定已有实例:onNewWant;新实例:onCreate需实现AbilityStage.onAcceptWant

3 个关键结论

  1. onCreatevsonNewWant:实例首次创建时调用onCreate,已有实例被再次唤起时调用onNewWantsingletonspecified(复用时)都会触发onNewWant,而multiton每次都触发onCreate

  2. specified模式的核心是onAcceptWant的返回值:相同返回值 → 复用实例;不同返回值 → 新建实例。返回值需要与业务标识严格对应,否则会产生重复实例。

  3. 资源消耗排序multiton>specified>singleton。多实例模式每个实例都持有独立资源,在设备内存紧张时更容易被系统回收。

http://www.jsqmd.com/news/697606/

相关文章:

  • 终极指南:如何用APK安装器在Windows电脑上直接运行安卓应用
  • 2026年盘点泉州隐形车衣服务,推荐靠谱品牌及费用情况 - myqiye
  • 分布式实时数据采集系统架构深度解析:闲鱼商品监控实战指南
  • Redis怎样利用Lua脚本批量抓取多类型数据
  • 深度学习实战:从零搭建CLIP——让AI看懂图像和文字的神奇配对
  • Voxtral-4B-TTS-2603行业落地:医疗问诊系统多语种用药指导语音生成
  • ToolOrchestra:基于思维链与工具调用的AI智能体工作流编排框架
  • 别再手动算了!用VerilogA在Cadence里快速验证你的8位二进制转换结果
  • 从仿真到调参:手把手教你用多同步旋转坐标系抑制PMSM的五七次谐波电流
  • 给实验室萌新的投稿避坑指南:手把手教你避开那些“分区高但口碑差”的期刊
  • 从零实现多头注意力机制:原理与TensorFlow实战
  • 2026年泉州隐形车衣排名,这些门店 - 工业设备
  • DeepSeek-V4预览版正式发布:Agent、世界知识和推理性能在开源领域领先——华为昇腾芯片适配、百万上下文、万亿参数、开源免费、国产大模型
  • 别再问网管了!手把手教你给Win10电脑设置固定IP(保姆级图文教程)
  • LCA笔记随性摘录2
  • 从‘tlsv1 unrecognized name’报错,聊聊那些年我们踩过的TLS协议兼容性坑(附wget2迁移指南)
  • 如何永久保存微信聊天记录:WeChatMsg终极数据备份方案
  • copyKAT实战:从单细胞转录组数据自动识别肿瘤细胞CNV与亚克隆结构
  • 探讨自固化绝缘防水包材,广东靠谱的供应商费用怎么算 - mypinpai
  • 6年网站建设经验总结:花钱推广不如做好百度自然收录
  • 硕博论文写作干货|告别延期,从开题到答辩全流程实操指南
  • 谁才是重庆公认的纹眉天花板?久匠以品质定义本地行业典范 - 企业博客发布
  • TEKLauncher:ARK生存进化游戏管理解决方案
  • Beyond Compare 5专业版密钥生成:3种方法深度解析与技术实现
  • 别再只盯着USB和HDMI了!聊聊LVDS这个‘老将’为什么在工业屏和医疗设备里依然能打
  • 2026宜昌木材品牌制造商推荐,好用的信誉好的木材源头厂有哪些 - 工业品牌热点
  • 2026年全国纸箱定制与包装生产一站式采购指南:正定利豪金属如何破解企业供应链痛点 - 企业名录优选推荐
  • 别再只盯着延迟了!手把手教你拆解网络时延:传播时延 vs. 主机时延的测量与TCP优化实战
  • 告别Electron臃肿!用Tauri + Vue 3打造你的第一个超轻量桌面应用(附完整配置流程)
  • Keil同时开发ARM和C51?一个TOOLS.INI文件冲突解决全记录(附C51配置块)