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

ArkUI Stage模型企业级实用教程

ArkUI Stage模型企业级实用教程

ArkUI Stage模型企业级实用教程

本文档基于HarmonyOS NEXT API 12+官方标准,系统讲解Stage模型的核心概念、架构设计、开发流程与企业级最佳实践,帮助开发者快速掌握Stage模型下的应用开发能力,构建高性能、可扩展的企业级应用。

 

官方定位

Stage模型是HarmonyOS主推的应用模型,采用面向对象的设计思想,支持多窗口、多设备、分布式能力,是未来HarmonyOS应用开发的标准范式。FA模型已进入维护阶段,新应用建议全部采用Stage模型开发。

 

一、Stage模型核心概念

1.1 架构设计

Stage模型采用"UIAbility-UI页面-组件"的三层架构:

应用 → UIAbility(1-N个) → AbilityStage → UI页面(1-N个) → 自定义组件 → 基础组件

每个UIAbility对应一个独立的业务模块,拥有独立的上下文和生命周期

1.2 核心组件说明

组件

作用

说明

UIAbility

应用组件入口

对应一个独立的业务模块,拥有独立的生命周期和窗口,支持单独启动

AbilityStage

运行时容器

UIAbility的运行容器,同一工程中所有UIAbility共享同一个AbilityStage实例

WindowStage

窗口管理器

管理UIAbility的窗口,包括窗口大小、位置、显示隐藏等

Context

上下文环境

提供应用运行时环境,可获取资源、启动Ability、访问系统服务等

Router

页面路由

管理UI页面之间的跳转、参数传递、回退等操作

1.3 与FA模型对比

特性

Stage模型

FA模型

架构设计

面向对象,组件化架构

面向页面,轻量架构

进程模型

支持多进程、多实例

单进程、单实例

窗口管理

多窗口支持,窗口独立管理

单窗口限制

分布式能力

原生支持分布式调度

分布式能力有限

生命周期

完善的生命周期管理

生命周期相对简单

代码复用

高,支持组件级、模块级复用

较低,页面级复用

适用场景

复杂应用、多模块应用、分布式应用

简单应用、单页面应用

二、生命周期管理

2.1 UIAbility生命周期

 

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import type Want from '@ohos.app.ability.Want';

export default class EntryAbility extends UIAbility {
  /**
   * Ability创建时调用,全局只调用一次
   * @param want 启动参数
   * @param launchParam 启动参数
   */
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    console.log('Ability onCreate');
    // 全局初始化操作:初始化SDK、配置全局参数等
  }

  /**
   * Ability变为可见时调用
   */
  onWindowStageCreate(windowStage: window.WindowStage): void {
    console.log('Ability onWindowStageCreate');
    // 加载页面,设置UI
    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        console.error('加载页面失败', JSON.stringify(err));
        return;
      }
      // 获取窗口实例,设置窗口属性
      windowStage.getMainWindow((err, window) => {
        if (!err) {
          window.setLayoutFullScreen(true); // 全屏显示
        }
      });
    });
  }

  /**
   * Ability进入前台时调用
   */
  onForeground(): void {
    console.log('Ability onForeground');
    // 恢复暂停的操作:恢复动画、重新注册监听等
  }

  /**
   * Ability进入后台时调用
   */
  onBackground(): void {
    console.log('Ability onBackground');
    // 暂停不必要的操作:暂停动画、注销监听、释放资源等
  }

  /**
   * Ability窗口销毁时调用
   */
  onWindowStageDestroy(): void {
    console.log('Ability onWindowStageDestroy');
    // 释放窗口相关资源
  }

  /**
   * Ability销毁时调用
   */
  onDestroy(): void {
    console.log('Ability onDestroy');
    // 全局资源释放:关闭数据库、注销全局监听等
  }
}

2.2 页面生命周期

 

@Entry
@Component
struct IndexPage {
  /**
   * 页面创建时调用,每次进入页面都会调用
   */
  aboutToAppear(): void {
    console.log('页面 aboutToAppear');
    // 页面初始化:加载数据、注册页面级监听
  }

  /**
   * 页面布局完成后调用
   */
  onPageShow(): void {
    console.log('页面 onPageShow');
    // 页面显示时的操作:恢复播放、更新数据等
  }

  /**
   * 页面即将隐藏时调用
   */
  onPageHide(): void {
    console.log('页面 onPageHide');
    // 页面隐藏时的操作:暂停播放、保存状态等
  }

  /**
   * 页面销毁时调用
   */
  aboutToDisappear(): void {
    console.log('页面 aboutToDisappear');
    // 页面资源释放:注销监听、取消请求等
  }

  build() {
    Column() {
      Text('首页')
        .fontSize(30)
    }
    .width('100%')
    .height('100%')
  }
}

2.3 生命周期触发流程

1. 应用冷启动:onCreate → onWindowStageCreate → onForeground → aboutToAppear → onPageShow

2. 应用切后台:onPageHide → onBackground

3. 应用切前台:onForeground → onPageShow

4. 页面跳转:新页面aboutToAppear → 旧页面onPageHide → 新页面onPageShow

5. 页面回退:旧页面onPageShow → 新页面aboutToDisappear

6. 应用退出:onPageHide → onBackground → onWindowStageDestroy → onDestroy

三、工程结构与配置

3.1 标准工程结构

 

entry/src/main/
├── ets/                     # 业务代码目录
│   ├── entryability/        # Ability入口
│   │   └── EntryAbility.ets
│   ├── pages/               # 页面文件
│   │   ├── Index.ets
│   │   ├── Login.ets
│   │   └── UserCenter.ets
│   ├── common/              # 公共资源
│   │   ├── components/      # 公共组件
│   │   ├── utils/           # 工具函数
│   │   ├── constants/       # 常量定义
│   │   └── api/             # 网络请求
│   ├── features/            # 业务特性模块
│   │   ├── home/            # 首页模块
│   │   ├── product/         # 商品模块
│   │   └── order/           # 订单模块
│   └── router/              # 路由配置
├── resources/               # 资源文件
│   ├── base/                # 基础资源
│   │   ├── element/         # 字符串、颜色、数值等
│   │   ├── media/           # 图片、音视频等
│   │   └── profile/         # 配置文件
│   ├── en_US/               # 英文资源
│   └── zh_CN/               # 中文资源
└── module.json5             # 模块配置文件

3.2 module.json5配置

 

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "phone",
      "tablet"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages", // 页面路由配置
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ]
  }
}

3.3 路由配置(main_pages.json)

 

{
  "src": [
    "pages/Index",
    "pages/Login",
    "pages/UserCenter",
    "pages/product/ProductList",
    "pages/product/ProductDetail",
    "pages/order/OrderList",
    "pages/order/OrderDetail"
  ]
}

四、核心功能开发

4.1 页面路由与参数传递

基础路由跳转

 

import router from '@ohos.router';

// 基础跳转
router.pushUrl({
  url: 'pages/Login'
});

// 带参数跳转
router.pushUrl({
  url: 'pages/product/ProductDetail',
  params: {
    productId: '123456',
    productName: '华为Mate 60 Pro'
  }
});

// 替换当前页面
router.replaceUrl({
  url: 'pages/Home'
});

// 返回上一页
router.back();

// 返回指定页面
router.back({
  url: 'pages/Home'
});

// 清空页面栈并跳转
router.clear();
router.pushUrl({ url: 'pages/Login' });

参数接收

 

import router from '@ohos.router';

@Entry
@Component
struct ProductDetailPage {
  @State productId: string = '';
  @State productName: string = '';

  aboutToAppear() {
    // 获取路由参数
    const params = router.getParams() as Record; if (params) { this.productId = params.productId; this.productName = params.productName; } // 根据productId加载商品详情 this.loadProductDetail(this.productId); } loadProductDetail(productId: string) { // 加载商品详情逻辑 } build() { Column() { Text(`商品ID: ${this.productId}`) Text(`商品名称: ${this.productName}`) } .width('100%') .height('100%') } }

4.2 全局Context使用

 

import common from '@ohos.app.ability.common';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';

// 获取全局Context
const context = getContext(this) as common.UIAbilityContext;

// 1. 启动其他Ability
context.startAbility({
  bundleName: 'com.example.myapp',
  abilityName: 'SecondAbility'
});

// 2. 获取资源
const appName = context.resourceManager.getStringSync($r('app.string.app_name').id);
const icon = context.resourceManager.getMediaContentSync($r('app.media.icon').id);

// 3. 权限申请
let atManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(context, [
  'ohos.permission.INTERNET',
  'ohos.permission.LOCATION'
]).then((result) => {
  console.log('权限申请结果', JSON.stringify(result));
});

// 4. 获取应用信息
const appInfo = context.applicationInfo;
console.log('应用包名', appInfo.bundleName);
console.log('应用版本', appInfo.versionName);

// 5. 获取目录路径
const cacheDir = context.cacheDir; // 缓存目录
const filesDir = context.filesDir; // 文件目录
const tempDir = context.tempDir; // 临时目录

4.3 全局状态管理

使用AppStorage实现全局状态共享

 

// AbilityonCreate中初始化全局状态
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  // 初始化用户信息
  AppStorage.setOrCreate('userInfo', null); // 初始化登录状态 AppStorage.setOrCreate('isLogin', false); // 初始化主题 AppStorage.setOrCreate('theme', 'light'); } // 在页面中使用全局状态 @Entry @Component struct UserCenterPage { @StorageLink('userInfo') userInfo: UserInfo = null; @StorageLink('isLogin') isLogin: boolean = false; build() { Column() { if (this.isLogin) { Text(`欢迎回来,${this.userInfo?.name}`) Button('退出登录') .onClick(() => { this.logout(); }) } else { Button('去登录') .onClick(() => { router.pushUrl({ url: 'pages/Login' }); }) } } } logout() { // 清除全局状态 AppStorage.set('userInfo', null); AppStorage.set('isLogin', false); // 跳转到登录页 router.clear(); router.pushUrl({ url: 'pages/Login' }); } }

五、多Ability开发

5.1 创建新的Ability

DevEco Studio中右键点击模块 → New → Ability,选择模板后自动生成Ability相关文件,自动更新module.json5配置。

5.2 Ability间跳转与数据传递

 

// AbilityA中启动AbilityB并传递参数
const context = getContext(this) as common.UIAbilityContext;
context.startAbility({
  bundleName: 'com.example.myapp',
  abilityName: 'AbilityB',
  parameters: {
    userId: '123',
    userName: '张三'
  }
}, (err) => {
  if (err) {
    console.error('启动AbilityB失败', err);
  }
});

// AbilityBonCreate中接收参数
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  const userId = want.parameters?.userId as string;
  const userName = want.parameters?.userName as string;
  console.log('接收参数', userId, userName);
}

// AbilityB返回结果给AbilityA
// AbilityA中使用startAbilityForResult
context.startAbilityForResult({
  bundleName: 'com.example.myapp',
  abilityName: 'AbilityB'
}).then((result) => {
  console.log('AbilityB返回结果', JSON.stringify(result));
  const code = result.resultCode;
  const data = result.want?.parameters;
});

// AbilityB中设置返回结果
const context = getContext(this) as common.UIAbilityContext;
context.terminateSelfWithResult({
  resultCode: 0, // 0表示成功
  want: {
    parameters: {
      result: '操作成功'
    }
  }
});

5.3 多窗口开发

 

// 创建新窗口
import window from '@ohos.window';

const context = getContext(this) as common.UIAbilityContext;
window.createWindow(context, 'second_window', window.WindowType.TYPE_APPLICATION).then((win) => {
  // 设置窗口大小和位置
  win.resize(600, 800);
  win.moveTo(100, 100);
  // 加载页面
  win.loadContent('pages/SecondWindow');
  // 显示窗口
  win.show();
});

// 获取所有窗口
window.getAllWindows().then((windows) => {
  console.log('窗口数量', windows.length);
});

// 关闭指定窗口
window.findWindow('second_window').then((win) => {
  win.destroy();
});

六、企业级最佳实践

6.1 架构设计规范

• 模块化拆分:按业务领域拆分为独立的Ability,每个Ability对应一个独立的业务模块

• 分层架构:采用UI层-业务逻辑层-数据层的三层架构,各层职责清晰

• 依赖注入:使用依赖注入框架管理对象依赖,降低耦合度

• 单一职责:每个Ability、页面、组件只负责单一功能

6.2 路由管理规范

• 路由常量统一管理:所有页面路径定义为常量,避免硬编码

• 路由守卫:封装路由跳转方法,实现权限校验、登录拦截等功能

• 参数类型安全:定义路由参数接口,确保参数类型正确

• 页面栈管理:合理控制页面栈大小,避免页面层级过深

 

// 路由常量定义
export enum RouterPath {
  HOME = 'pages/Index',
  LOGIN = 'pages/Login',
  USER_CENTER = 'pages/UserCenter',
  PRODUCT_LIST = 'pages/product/ProductList',
  PRODUCT_DETAIL = 'pages/product/ProductDetail'
}

// 路由参数类型定义
export interface ProductDetailParams {
  productId: string;
  productName?: string;
}

// 封装路由工具类
export class RouterUtil {
  /**
   * 跳转到商品详情页
   * @param params 商品参数
   */
  static goToProductDetail(params: ProductDetailParams): void {
    // 登录校验
    if (!AppStorage.get('isLogin')) { router.pushUrl({ url: RouterPath.LOGIN }); return; } // 跳转页面 router.pushUrl({ url: RouterPath.PRODUCT_DETAIL, params: params }); } }

6.3 性能优化实践

• 懒加载:非首屏页面和组件使用懒加载,减少启动时间

• 资源优化:图片等资源按需加载,避免一次性加载过多资源

• 内存管理:在onBackground和onDestroy中及时释放大资源

• 启动优化onCreate中只做必要的初始化,非必要操作延迟执行

• 异步操作:耗时操作全部异步执行,避免阻塞主线程

6.4 安全规范

• 权限最小化:只申请必要的权限,避免过度申请

• 数据加密:敏感数据存储和传输时加密处理

• 输入校验:所有用户输入都要做合法性校验

• WebView安全WebView启用安全配置,禁止执行不安全的JS代码

七、常见问题与解决方案

问题现象

解决方案

页面跳转时提示"路由不存在"

检查页面路径是否正确,是否在main_pages.json中注册

获取Context时报错"context is undefined"

确保在组件初始化完成后调用getContext,建议在aboutToAppear中获取

Ability启动缓慢

优化onCreate中的初始化逻辑,减少同步阻塞操作

页面跳转时参数丢失

避免传递大对象,参数类型支持JSON序列化

多窗口切换时状态丢失

使用AppStorage或持久化存储保存状态,避免依赖组件内部状态

后台运行时被系统杀死

关键状态及时持久化,Ability重启时恢复状态

权限申请被拒绝后功能异常

添加权限拒绝的友好提示和降级处理逻辑

八、开发检查清单

1. ✅ 所有页面都在main_pages.json中正确注册

2. ✅ 路由跳转使用统一的常量路径,无硬编码

3. ✅ 生命周期方法中正确处理资源的申请与释放

4. ✅ 全局状态使用AppStorage等统一管理,避免跨组件传参混乱

5. ✅ 敏感权限申请有明确的使用说明和降级处理

6. ✅ 后台操作在应用切后台时正确暂停

7. ✅ 大对象、大资源在使用完后及时释放

8. ✅ 所有用户输入都做了合法性校验

9. ✅ 错误场景都有友好的用户提示

10. ✅ 页面跳转和返回逻辑符合用户操作习惯

 

学习建议

Stage模型是HarmonyOS开发的核心,建议开发者深入理解生命周期和Context机制,这是开发稳定可靠应用的基础。多动手实践,结合官方示例理解各种场景的处理方式。

 

文档版本:V1.0 | 适配版本:HarmonyOS NEXT API 12+ | 更新日期:2024年4月