#HarmonyOS NEXT体验官# 鸿蒙应用开发-你不得不知道的UIAbility组件 原创
UIAbility概念
鸿蒙应用是基于Ability组件来开发的,UIAbility是Ability类型中的一种,是带有UI类型的Ability,为应用提供window窗口绘制以及交互。
每一个UIAbility实例,都对应于一个最近任务列表中的任务。一个UIAbility可以对应于多个页面,建议将一个独立的功能模块放到一个UIAbility中。

Router - UIAbility内的页面跳转
我们指定一个UIAbility可以有多个Page页面。启动一个Page是通过router来完成的。
router.pushUrl
//  在单例模式下,若栈中存在改实例,则会将实例移至栈顶,栈数量是不变的,若栈中不存在改实例,改实例则会入栈顶,栈数量+1
//  在标准模式(多实例)下,无论栈中是否存在实例,都会将新页面实例加入栈顶,栈数量+1
router.pushUrl({ url: RouteConstants.RANK_PAGE_URL,
params: { src: "main page push 传来的数据" } },
router.RouterMode.Single
)
url:页面路径params:跳转携带的参数mode:启动模式Single:单例模式- 在单例模式下,若栈中存在改实例,则会将实例移至栈顶,栈数量是不变的,若栈中不存在改实例,改实例则会入栈顶,栈数量+1
 
Standard:多实例模式- 在标准模式(多实例)下,无论栈中是否存在实例,都会将新页面实例加入栈顶,栈数量+1
 
页面路径需要在resources/profile/main_pages.json文件中注册。在目标页面接收参数,可以在aboutToAppear接受参数。
  aboutToAppear() {
    // 实战中最好对参数属性判空,避免闪退
    let src = router.getParams()['src']
    LogUtils.d(src)
    LogUtils.d("stack size: "+router.getLength())
  }
  
返回上一页或返回指定页面,也是可以携带参数返回的。
 //  返回上一页
 router.back()
 // 返回指定页
 router.back({ url: RouteConstants.EXAMPLE_MAIN_PAGE_URL, params: { src: "来自上页的数据" } })
当返回有携带参数时,可以在目标组件页面的onPageShow()方法来接收,如下:
onPageShow() {
    // 页面显示时被调用
    // 初次创建页面时、从后台进入前台时
    LogUtils.d("onPageShow")
    LogUtils.d("stack size: " + router.getLength())
    // 接受上页返回携带的数据,注意需要判空,不然会闪退
    if (router.getParams() != null ) {
      let params = (router.getParams() as Record<string, string>)
      LogUtils.d("scr: " + params.src)
    
    }
}
router.replaceUrl
router.replaceUrl的参数是与router.pushUrl是一样的,区别是启动模式的表现。
// 在单例模式下,若栈中存在实例,则会将栈顶的实例移出栈,然后将目标实例移至栈顶,栈数据-1,若栈中不存在实例,则新实例入栈顶替换原来栈顶的实例,栈数量不变
// 在标准模式(多实例)下,无论栈中是否存在实例,都会将新页面实例加入栈顶并替换原栈顶实例,栈数量不变
router.replaceUrl({ url: RouteConstants.RANK_PAGE_URL, params: { src: "main page replace 传来的数据" } })
- 单例模式下,若栈中存在实例,则会将栈顶的实例移出栈,然后将目标实例移至栈顶,栈数据-1,若栈中不存在实例,则新实例入栈顶替换原来栈顶的实例,栈数量不变。
 - 标准模式(多实例)下,无论栈中是否存在实例,都会将新页面实例加入栈顶并替换原栈顶实例,栈数量不变。
 
由于当前页被替换了,因此在返回时携带参数是无效的,无法接收的。
UIAbility生命周期
从桌面点击打开应用,或者返回桌面等操作,UIAbility的生命周期都会发生变化。
export default class EntryAbility extends UIAbility {
  /**
   * 1、UIAbility实例创建时,系统会回调onCreate方法,UI不可见
   *  可以用于sdk的初始化,类似于Android的Application#onCreate()方法
   * @param want
   * @param launchParam
   */
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
 
  }
  /**
   * 6、在UIAbility销毁时触发。可以在onDestroy回调中进行系统资源的释放、数据的保存等操作。
   */
  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }
  /**
   * 2、在创建UIAbility实例后,进入前台前,系统会创建一个WindowStage,然后回调onWindowStageCreate方法
   * 可以用于UI页面加载、设置WindowStage的事件订阅,其中入口页面就是在这里设置的,通过WindowStage#loadContent
   * 一个UIAbility只有一个WindowStage,
   * @param windowStage
   */
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // 根页面组件就是在完成加载的
    windowStage.loadContent("pages/LoginPage", (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }
  /**
   * 5、在UIAbility实例销毁之前,则会先进入onWindowStageDestroy回调,我们可以在该回调中释放UI页面资源。
   */
  onWindowStageDestroy(): void {
  }
  /**
   * 3、从后台(桌面、任务栏)切换到前台,ui可见
   * 可以向系统申请需要的资源,比如定位、播放视频
   */
  onForeground(): void {
  }
  /**
   * 4、从前台切换到后台,ui不可见
   * 可以释放一些资源,比如停止定位,暂停播放视频
   */
  onBackground(): void {
  }
}
用户使用应用的程序退出功能,会调用
UIAbilityContext的terminalSelf()方法,从而完成UIAbility销毁。或者用户使用最近任务列表关闭该UIAbility实例时,也会完成UIAbility的销毁。
UIAbility的启动模式及交互
UIAbility三种启动模式:
singleton(单实例模式):默认模式,每次调用startAbility()启动UIAbility时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例,系统中只存在唯一一个该UIAbility实例。multiton(多实例模式):每次调用startAbility()方法时,都会在应用进程中创建一个该类型的UIAbility实例。specified(指定实例模式):根据业务需要是否创建一个新的UIAbility实例。
启动UIAbility的基本使用:
一、在module.json5注册UIAbility组件
// 注册UIAbility
  {
    "name":"LaunchModeAbility", 
    "icon": "$media:ic_registration_success",
    "label": "$string:ability_test_name",
    "srcEntry": "./ets/ability/LaunchModeAbility.ets",
    "startWindowIcon": "$media:ic_registration_success",
    "startWindowBackground": "$color:start_window_background",
     // 启动模式
    "launchType": "singleton"
  }
name: 名称,尽量与类名一样icon:图标,在后台任务栏的可以看到label:UIAbility的名称srcEntry:UIAbility的相对路径launchType:启动模式
二、启动UIAbility
通过UIAbilityContext来调用startAbility()方法来启动。
private context = getContext(this) as common.UIAbilityContext
...
// 启动
  let want = {
    bundleName:"com.xxxx.demo",
    abilityName:"LaunchModeAbility",
    moduleName:"entry",
    parameters: { src: "main page param " + this.counter }
  }
  this.context.startAbility(want)
bundleName:UIAbility所在应用的包名abilityName:UIAbility名称moduleName:UIAbility所在模块的名称parameters:启动携带的参数,可以在UIAbility的onCreate()中接收。
Want实例不能通过new的方式来创造,因为没有默认的构造函数,只能通过字面量的方式来定义的一个实例。
三、接收启动的参数
export  default class LaunchModeAbility extends UIAbility{
   static readonly TAG:string = "LaunchModeAbility"
  onCreate(want: Want, param: AbilityConstant.LaunchParam){
    // 接收传递的参数
    let src = want.parameters.src
    LogUtils.d("LaunchModeAbility onCreate  src: "+src)
  }
  onDestroy(){
    LogUtils.d("LaunchModeAbility onDestroy")
  }
  onWindowStageCreate(windowStage: window.WindowStage) {
    LogUtils.d("onWindowStageCreate")
    // 加载根页面组件
    windowStage.loadContent(RouteConstants.TEST_PAGE_URL, (error, data) => {
      if (error.code) {
        LogUtils.e(error.message)
      }
    })
  }
  
}  
推荐
这样推荐一个页面导航库:




















