HarmonyOS:UIAbility进阶
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤博客园地址:为敢技术(https://www.cnblogs.com/strengthen/ )
➤GitHub地址:https://github.com/strengthen
➤原文地址:https://www.cnblogs.com/strengthen/p/18487373
➤如果链接不是为敢技术的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
2、ExtensionAblility组件:定义见下图。各类型的ExtensionAbility组件均由相应的系统服务统一管理。例如InputMethodExtensionAbility组件由输入法管理服务统一管理。目前ExtensionAbility组件类型有:
(1)、用于输入法场景的InputMethodExtensionAbility。
(2)、用于闲时任务场景的WorkSchedulerExtensionAbility。在IDE中支持选中Module后创建不同类型的ExtensionAbility组件文件。如下图所示:
3、HAP:定义见下图。一个APP可以包含一个或多个HAP。当HAP中的代码首次被加载到进程中时,也就是Module初始化时,系统会首先创建一个AbilityStage实例。包含UIAbility组件或者ExtensionAbility组件的Module可以单独运行,该类型Module运行时会编译生成一个.hap文件,即:HAP。
4、AbilityStage:定义见下图。AbilityStage是一个Module级别的组件容器,可以管理Module中的UIAbility组件和ExtensionAbility组件。AbilityStage与编译期的HAP是一一对应关系。
5、上述四个概念在运行期和编译期的关系。
在开发时,一个项目可能需要包含一个或多个可以单独运行的Module,对应到运行期,一个应用即一个Application,就可能包含1个或多个AbilityStage。对应到编译期,一个App可能包含一个或多个HAP。 在运行期, 每个AbilityStage持有Module上定义的UIAbility组件和ExtensionAbility组件。当UIAbility组件首次启动时,系统会为UIAbility组件创建实例,并将该实例与持有它的AbilityStage实例关联,开发者可以通过AbilityStage获取该UIAbility实例的运行时信息。UIAbility实例创建后,系统为该实例创建一个WindowStage实例,并一对一绑定,WindowStage提供了应用进程类窗口管理器的作用,它持有一个主窗口,该主窗口为ArkUI提供了绘制区域,并管理多个ArkUI页面,在运行期系统为Application、AbilityStage、UIAbility组件和ExtensionAbility组件分别提供了对应的上下文环境,分别是ApplicationContext、AbilityStageContext、UIAbilityContext组件和ExtensionAbilityContext,开发者可以通过上下文环境调用各种资源和能力。运行期和编译期的基本概念中最重要的就是UIAbility组件,UIAbility组件的核心是生命周期,当用户启动、使用和退出应用时,应用的UIAbility实例会在其生命周期的不同状态之间转换。
UIAbility组件、AbilityStage、WindowStage间的生命周期的关系。
UIAbility组件和WindowStage各自拥有一套生命周期,在设备上首次启动某个UIAbility组件时,UIAbility组件、AbilityStage、WindowStage的生命周期执行顺序如下图所示:系统首先创建持有该UIAbility组件的AbilityStage实例,创建成功后,执行其onCreate生命周期回调函数,开发者可以通过重写该函数,再进行一些Module级别的资源初始化,或临时全局共享数据的设置工作,接下来,系统会为该UIAbility组件创建实例,创建成功后绘制执行其onCreate生命周期回调函数,可以在该函数中初始化业务逻辑,例如变量定义、资源加载等,用于后续的UI展示,onCreate函数执行完成后,系统将为UIAbility实例创建一个WindowStage实例,创建成功后实行UIAbility实例的onWindowStageCreate回调函数,可以通过该函数,获取主窗口信息、设置UI加载界面,以及监听WindowStage的生命周期变化,相应的,在UIAbility实例销毁之前,将先进入onWindowStageDestroy回调函数,开发者可以在该函数中释放UI界面资源,例如:在onWindowStageDestroy函数中注销WindowStage的事件,可以看到应用组件和窗口的生命周期是松耦合的。这种设计模式有如下好处:
(1)、业务逻辑和UI逻辑分离。开发者可以在UIAbility组件中处理与页面无关的业务逻辑,如打开蓝牙,连接数据库等,在WindowStage持有的窗口上,通过ArkUI处理界面相关的业务逻辑。
(2)、便于系统对应用组件进行裁剪。例如:对无屏设备,系统在运行应用时,不会创建窗口模块,有利于减少系统ROM空间占用。
(3)、 在多设备(桌面设备和移动设备上),应用组件可使用同一套生命周期,应用运行时,系统会自动判断设备,并根据不同设备的窗口形态变换,执行不同的生命周期变化流程。
以在单窗口形态上和多窗口形态上任务切换的场景为例,在设备上一个UIAbility实例对应于任务视图的一个任务,在单窗口形态如移动设备上,当用户从任务一切换到任务二时,对于任务一,会触发其WindowStage的InActive失焦和Hidden隐藏生命周期,继而触发其UIAbility实例的Background生命周期。对于任务二,会触发其WindowStage的Shown显式和Active聚集生命周期,继而触发其UIAbility实例的Foreground生命周期。同理,多窗口形态(如2in1)见下图:
2、AbilityStage的创建与使用。DevEco默认工程中未自动生成AbilityStage,如需要使用AbilityStage的能力,需要手动新建一个AbilityStage文件。
(1)、新建AbilityStage目录:首先创建AbilityStage目录,如下图,在需要创建AbilityStage的Module的ets目录下,鼠标右键选择:【New-Directory】,创建一个目录并命名为myabilitystage,创建完成后,工程目录结构如下图所示。
2、三种启动模式的开发和执行过程。
第二步:在调用方的页面上开发启动UIAbility组件的逻辑函数,在该逻辑函数中包含三个步骤:
(a)、获取调用方的UIAbilityContext。以此获得启动UIAbility组件的能力。
(b)、创建want,在want中指定需要启动的UIAbility 组件名为:SpecifiedAbility,并自定义一个唯一参数,用于标识每个UIAbility实例。如:此处自定义参数名为instanceKey,该参数值通过自定义函数getInstanceKey获取,在点击打开文档的操作时,可以将文档路径和文档名拼接的字符串,作为入参传入getInstanceKey函数,在getInstanceKey函数中进行逻辑处理并返回唯一key值。
(c)、调用UIAbilityContext的startAbility函数,并将Want函数传入。
指定实例启动模式的执行过程:
当调用方通过startAbility函数启动UIAbility组件时,系统启动被调用的UIAbility组件,在启动被调用的UIAbility组件之前,系统先触发持有被调用的UIAbility组件的AbilityStage的onAcceptWant回调函数,该函数会解析调用方传递的want信息,并返回被调用的UIAbility实例的唯一key值。系统根据返回的唯一key值,判断当前进程中该key值对应的UIAbility实例释放已经存在,若存在,则系统执行该UIAbility实例的onNewWant回调函数,之后UIAbility实例进入Foreground生命周期,并执行其onForeground回调函数,若不存在,则系统新建被调用的UIAbility组件实例,并执行其onCreate生命周期回调函数,随后创建对应的WindowStage实例,并执行UIAbility实例的onWindowStageCreate回调函数,最后UIAbility实例进入Foreground生命周期,并执行其onForeground回调函数。以上就是UIAbility组件指定实例启动模式的全部执行过程。
2、使用Want启动UIAbility组件有两种形式,显式Want启动和隐式Want启动。
(1)、显式Want启动:是指在启动UIAbility组件时,在Want参数中指定了UIAbility组件名:abilityName,和应用包名:bundleName,这种形式用于启动某个明确UIAbility组件的场景。
(2)、隐式Want启动:是指在启动UIAbility组件时,在Want参数中不指定UIAbility组件名:abilityName,而是设置被启动应用具备的能力和类型等筛选条件。系统再根据筛选条件匹配支持该条件的所有应用。这种启动形式用于希望使用某个应用的能力,而不关心提供该能力的具体应用的场景。
3、显式Want启动UIAbility组件的开发过程,包含3个步骤:
(1)、获取调用方的上下文信息UIAbilityContext。以此获取启动UIAbility组件的能力。
(2)、创建显式Want。在Want中明确指定要启动的应用包名:bundleName,和UIAbility组件名:abilityName。在Want的parameters字段中,可以自定义传递给要启动的UIAbility组件的信息,如此处自定义了参数:info。该参数值为:来自EntryAbility Index页面。在Want中还可以配置很多其他参数,如:deviceId表示启动的应用所在的设备,当deviceId为空或者不设置该字段时表示本设备。更多参数的详细使用可以参看官网指南。
(3)、调用UIAbilityContext的startAbility函数,并将刚创建的Want对象作为参数传入,系统启动调用的UIAbility组件时,对于被调用的UIAbility组件,可以通过启动时的回调函数,获取到调用方传递的Want对象,在回调函数中,通过解析Want对象可以获取调用方传递的信息,如调用方的PID,应用名和自定义传递的信息等。若被调用的UIAbility组件时冷启动,可以通过onCreate函数接收Want对象,若被调用的UIAbility组件是热启动,可以通过onNewWant函数接收Want对象。
调用方页面:
被调用方UIAbility文件:通过onCreate函数的入参获取调用方传递的Want对象,通过解析Want对象获取调用方传递的自定义信息:info
3、隐式Want启动UIAbility组件的开发过程。
启动浏览器:
上面展示了隐式启动浏览器并打开网址的过程,在页面上点击【拉起浏览器类型应用并打开华为官方网址】时,系统将拉起应用中的浏览器类型应用,并自动打开华为官方网址。具体代码实现:
(1)、需要知道被调用的应用所支持的能力。
在被调用方的module.json5配置文件中,找到需要调用的UIAbility组件的相关配置信息,其中"skills"字段表示该UIAbility组件所支持的能力集,主要包含两个维度:
entities:表示UIAbility组件额外的类别信息,如:浏览器、视频播放器。
actions:表示UIAbility组件支持的通用操作,如:查看、分享数据。
假设浏览器应用在entities字段中添加了“entity.system.browsable”表明其为浏览器类型,在actions字段中添加了“ohos.want.action.viewData”表明应用支持查看数据。
(2)、在知道了被调用方的应用能力配置信息后,在调用方启动UIAbility组件时,需要做如下开发:
第一步:获取被调用方的UIAbilityContext,以此获取启动UIAbility组件的能力,
第二步:创建隐式Want。在Want中不指定abilityName字段,而是指定一系筛选条件。根据前面获得的浏览器应用配置信息,下图示例代码在want中设置筛选条件,entities字段为[entity.system.browsable],action字段为:ohos.want.action.viewData,为了浏览器应用启动后能够自动打开华为官网,在Want中指定跳转的网址信息,即设置uri字段值为:"https://www.huawei.com/cn"。
第三步:调用UIAbilityContext的startAbility方法,并将刚创建的Want作为参数传入,隐式启动UIAbility组件。
(3)、使用隐式Want启动UIAbility组件时,系统将根据Want对象中的筛选条件匹配符合条件的应用,有以下三种匹配结果:
(a)、未匹配到满足条件的UIAbility组件时,启动失败。
(b)、匹配到一个满足条件的UIAbility组件时,直接启动该UIAbility组件。
(c)、匹配到多个满足条件的UIAbility组件时,系统弹出选择框,提供所有满足条件的应用供用户选择。
匹配完成后,可以在startAbility方法的.then()方法和.catch()方法中,分别处理启动成功的业务逻辑和启动失败的业务逻辑。以上就完成了隐式Want启动浏览器类型的应用开发。