【HarmonyOS】掌握 Stage 模型的核心概念与应用

news/2024/7/21 9:42:36 标签: harmonyos, 华为, 鸿蒙开发, 经验分享, 生命周期

        从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是什么?鸿蒙仅仅是一个手机操作系统吗?它的出现能够和Android和IOS三分天下吗?它未来的潜力能否制霸整个手机市场呢?

抱着这样的疑问和对鸿蒙开发的好奇,让我们开始今天对Stage应用模型的掌握吧!

目录

Stage应用模型

应用配置文件

UIAbility生命周期

页面及组件生命周期

UIAbility启动模式


Stage应用模型

应用模型是HarmonyOS为开发者提供的应用程序所需能力的抽象提炼,它提供了应用程序必备的组件和运行机制。有了应用模型,开发者可以基于一套统一的模型进行应用开发,使应用开发更简单、高效。随着系统的演进发展,HarmonyOS先后提供了两种应用模型:

FA(Feature Ability)模型

HarmonyOS早期版本开始支持的模型,已经不再主推
Stage模型

Harmony0S 3.1 Developer Preview版本开始新增的模型,是目前主推且会长期演进的模型。在该模型中,由于提供了AbilityStage、WindowStage等类作为应用组件和Window窗口的“舞台”,因此称这种应用模型为Stage模型。

那也就是说不仅是现在的harmonyos4版本,包括马上要发布的harmonyos next版本都会推荐大家去基于Stage模型去开发,因此接下来博主将着重讲解与Stage模型相关的知识:

应用配置文件

基于Stage模型开发的应用,经编译打包后,其应用程序包结构如下图应用程序包结构(Stage模型)所示。开发者需要熟悉应用程序包结构相关的基本概念。

详情请查看 官方文档 这里我们首先先讲解一下基于Stage模型应用的一些配置文件,Stage模型的应用配置文件主要分为以下两类:

应用的全局配置文件:配置全局信息,文件夹主要信息如下:

Module配置文件:配置模块信息,文件夹主要信息如下:

当我们想修改我们的应用名称时,可以点击右上角的编辑

进入到编辑器进行我们的修改,也是非常的方便:

修改完成之后,我们再回到我们本地的模拟器当中就能看到我们修改的名字发生变化了:

UIAbility生命周期

UIAbility是指具有界面交互能力的Ability。它可以提供应用程序的用户界面,响应用户的交互动作,并将用户的操作传递给应用程序。

UIAbility生命周期是指UIAbility在创建、启动、暂停、恢复和销毁过程中所经历的各个阶段。在项目的entryability中已经给与我们UIAbility生命周期函数的运行流程:

这里我们通过本地模拟器搭配控制台来演示 UIAbility生命周期 运行的流程:

页面及组件生命周期

页面:即应用的 UI 页面。可以由一个或者多个自定义组件组成,@Entry 装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个@Entry。只有被@Entry 装饰的组件才可以调用页面的生命周期

页面生命周期,即被@Entry 装饰的组件生命周期,提供以下生命周期接口:

onPageShow:页面每次显示时触发。
onPageHide:页面每次隐藏时触发一次。
onBackPress:当用户点击返回按钮时触发。

组件生命周期,即一般用@Component 装饰的自定义组件的生命周期,提供以下生命周期接口:

aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其 build() 函数之前执行。
aboutToDisappear:在自定义组件即将析构销毁时执行。

生命周期流程如下图所示,下图展示的是被@Entry装饰的组件(首页)生命周期

具体实现的流程图如下:

接下来我们通过下面的这一段代码来实现页面及组件生命周期的执行流程:

// 入口组件
import router from '@ohos.router'
@Entry
@Component
struct Test {
  @State isShowChild: boolean = true // 是否显示自定义组件

  // 组件被创建之前
  aboutToAppear(){
    console.log('主组件被创建了')
  }
  // 组件被销毁了
  aboutToDisappear(){
    console.log('主组件被销毁了')
  }
  // 页面显示的时候
  onPageShow(){
    console.log('主页面被显示')
  }
  // 页面隐藏的时候
  onPageHide(){
    console.log('主页面被隐藏')
  }
  // 返回按钮被点击
  onBackPress(){
    console.log('返回按钮被点击')
  }
  build(){
    Column(){
      Text('我是主页面')
        .fontSize(40)
        .fontWeight(FontWeight.Bold)
      Row(){
        // 按钮动态显示子组件
        Button('点击')
          .onClick(()=>{
            this.isShowChild = !this.isShowChild
          })
        Button('离开当前页面')
          .onClick(()=>{
            router.pushUrl({ url: 'pages/router/test2' })
          })
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceAround)
      .margin(15)
      // 自定义组件
      if(this.isShowChild){
        test()
      }
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

// 自定义组件
@Component
struct test {
  @State message: string = '张三'
  // 组件被创建之前
  aboutToAppear(){
    console.log('子组件被创建了')
  }
  // 组件被销毁了
  aboutToDisappear(){
    console.log('子组件被销毁了')
  }
  build(){
    Column(){
      Text(`Hello ${this.message}`)
        .fontSize(30)
        .onClick(()=>{
          this.message = '李四'
        })
    }
  }
}

最终呈现的效果如下:

UIAbility启动模式

在前面我们提到Stage模型的应用,在启动时会先准备ability stage舞台,接着就可以基于它去创建UIAbility实例并且去启动它,对于UIAbility的启动模式有很多种,接下来将着重讲解最常用的四种:

Singleton启动模式:每一个UIAbility只存在唯一实例。默认是启动模式,任务列表中只会存在一个相同的UIAbility。以下给出动态图进行演示一下:

standard启动模式:每次启动UIAbility都会创建一个新的实例,在任务列表中可能存在一个或多个相同的UIAbility。修改module.json文件,进行如下配置更改UIAbility启动模式:

接下来我们对standard模式进行如下演示,可以看到实例对多次创建而且不会销毁:

multiton启动模式:每次启动UIAbility都会创建一个新的实例,在任务列表中只会存在一个UIAbility。如下进行演示:

specififed启动模式:每个UIAbility实例可以设置key标示启动UIAbility时,需要指定key,存在key相同实例直接被拉起,不存在则创建新实例。官方文档给我们很好的演示了:

在EntryAbility中,调用startAbility()方法时,在want参数中,增加一个自定义参数来区别UIAbility实例,例如增加一个"instanceKey"自定义参数。

// 在启动指定实例模式的UIAbility时,给每一个UIAbility实例配置一个独立的Key标识
// 例如在文档使用场景中,可以用文档路径作为Key标识
function getInstance() {
    // ...
}

let want = {
    deviceId: '', // deviceId为空表示本设备
    bundleName: 'com.example.myapplication',
    abilityName: 'FuncAbility',
    moduleName: 'module1', // moduleName非必选
    parameters: { // 自定义信息
        instanceKey: getInstance(),
    },
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(want).then(() => {
    // ...
}).catch((err) => {
    // ...
})

由于FuncAbility的启动模式配置为了指定实例启动模式,在FuncAbility启动之前,会先进入其对应的AbilityStage的onAcceptWant()生命周期回调中,解析传入的want参数,获取"instanceKey"自定义参数。根据业务需要通过AbilityStage的onAcceptWant()生命周期回调返回一个字符串Key标识。如果返回的Key对应一个已启动的UIAbility,则会将之前的UIAbility拉回前台并获焦,而不创建新的实例,否则创建新的实例并启动。

import AbilityStage from '@ohos.app.ability.AbilityStage';

export default class MyAbilityStage extends AbilityStage {
    onAcceptWant(want): string {
        // 在被调用方的AbilityStage中,针对启动模式为specified的UIAbility返回一个UIAbility实例对应的一个Key值
        // 当前示例指的是module1 Module的FuncAbility
        if (want.abilityName === 'FuncAbility') {
            // 返回的字符串Key标识为自定义拼接的字符串内容
            return `ControlModule_EntryAbilityInstance_${want.parameters.instanceKey}`;
        }

        return '';
    }
}

例如在文档应用中,可以对不同的文档实例内容绑定不同的Key值。当每次新建文档的时候,可以传入不同的新Key值(如可以将文件的路径作为一个Key标识),此时AbilityStage中启动UIAbility时都会创建一个新的UIAbility实例;当新建的文档保存之后,回到桌面,或者新打开一个已保存的文档,回到桌面,此时再次打开该已保存的文档,此时AbilityStage中再次启动该UIAbility时,打开的仍然是之前原来已保存的文档界面。  以如下步骤所示进行举例说明。     

1)打开文件A,对应启动一个新的UIAbility实例,例如启动“UIAbility实例1”。     

2)在最近任务列表中关闭文件A的进程,此时UIAbility实例1被销毁,回到桌面,再次打开文件A,此时对应启动一个新的UIAbility实例,例如启动“UIAbility实例2”。     

3)回到桌面,打开文件B,此时对应启动一个新的UIAbility实例,例如启动“UIAbility实例3”。     

4)回到桌面,再次打开文件A,此时对应启动的还是之前的“UIAbility实例2”。


http://www.niftyadmin.cn/n/5314502.html

相关文章

FRPS配置服务端(腾讯云)、客户端(PC电脑Windows、树莓派Debian)并设置虚拟域名

1.服务端(腾讯云):frps.ini [common] bind_port 7000 vhost_http_port8080 vhost_https_port44344 dashboard_port 7500 privilege_token your_password subdomain_host example.com use_encryption true encryption_method tls dashb…

XSS(跨站脚本攻击)漏洞介绍

简介 XSS(跨站脚本攻击)是一种常见的计算机安全漏洞,也是Web应用中最主流的攻击方式之一。它利用网站接收用户提交数据时未进行足够的转义处理或过滤不足的缺点,将恶意代码嵌入到Web页面中。当其他用户访问该页面时,嵌入的代码会被执行,从而导致盗取用户资料、利用用户身…

NodeJs 第十章 日志记录

日志在Web应用中是必不可少的,在系统调试或运行出现异常时,可以通过日志来进行排查,甚至利用日志可以进行数据统计。log4js 可以帮助我们在 Node 环境中记录日志 日志可以分为三个方面 level:日志级别(例如调试日志、信息日志、错…

HarmonyOS@Link装饰器:父子双向同步

Link装饰器:父子双向同步 子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 说明 从API version 9开始,该装饰器支持在ArkTS卡片中使用。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 装饰器使用规则说明 Link变…

C#-程序结构

C# 中的组织结构的关键概念是程序 (program)、命名空间 (namespace)、类型 (type)、成员 (member) 和程序集 (assembly)。 C# 程序由一个或多个源文件组成。 程序中声明类型,类型包含成员,并且可按命名空间进行组织。类和接口就是类型的示例。 字段 (field)、方法、属性和事件…

猫头虎博主第9期赠书活动:《YOLO目标检测》计算机AI视觉实战YOLO人工智能目标检测与跟踪图像处理深度学习图像检测书籍

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通Golang》…

2024.1.9

今天没有新学什么东西,因为今天基本上算是满课,所以说只得挤出一点使时间来复习一下以前写的代码,和做了几个学校的代码题(学校代码题有些还怪难的),今天的代码学习是大不如前几天的,十分不好&a…

【JVM 基础】 Java 类加载机制

JVM 基础 - Java 类加载机制 类的生命周期类的加载: 查找并加载类的二进制数据连接验证: 确保被加载的类的正确性准备: 为类的静态变量分配内存,并将其初始化为默认值解析: 把类中的符号引用转换为直接引用 初始化使用卸载 类加载器, JVM类加载机制类加载…