应用实例与项目结构
应用实例
每个 HarmonyOS 应用都从一个 UIAbility 开始。UIAbility 是带界面的能力单元,负责管理一组页面和生命周期。
typescript
// entry/src/main/ets/entryability/EntryAbility.ets
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit'
import { window } from '@kit.ArkUI'
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
// 应用创建时调用
console.info('EntryAbility onCreate')
}
onDestroy() {
// 应用销毁时调用
console.info('EntryAbility onDestroy')
}
onWindowStageCreate(windowStage: window.WindowStage) {
// 窗口创建时调用,加载入口页面
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
console.error('加载页面失败', JSON.stringify(err))
return
}
console.info('页面加载成功')
})
}
onWindowStageDestroy() {
// 窗口销毁时调用
}
onForeground() {
// 进入前台时调用
}
onBackground() {
// 进入后台时调用
}
}UIAbility 生命周期
onCreate → onWindowStageCreate → onForeground → onBackground → onWindowStageDestroy → onDestroy
↑______________________________________________↓| 生命周期 | 触发时机 | 典型用途 |
|---|---|---|
onCreate | 应用首次创建 | 初始化数据、读取配置 |
onWindowStageCreate | 窗口创建 | 加载入口页面 |
onForeground | 应用进入前台 | 恢复数据、刷新界面 |
onBackground | 应用进入后台 | 保存状态、释放资源 |
onWindowStageDestroy | 窗口销毁 | 清理窗口相关资源 |
onDestroy | 应用销毁 | 最终清理 |
页面组件
传给 windowStage.loadContent() 的是页面路径,对应的页面组件:
typescript
// entry/src/main/ets/pages/Index.ets
@Entry
@Component
struct Index {
// 页面级状态
@State title: string = '首页'
// 页面生命周期
aboutToAppear() {
console.info('页面即将显示')
}
aboutToDisappear() {
console.info('页面即将销毁')
}
onPageShow() {
console.info('页面显示')
}
onPageHide() {
console.info('页面隐藏')
}
build() {
Column() {
Text(this.title)
.fontSize(24)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}页面生命周期
aboutToAppear → build → onPageShow → onPageHide → aboutToDisappear
↑________________________________________________↓| 生命周期 | 触发时机 | 典型用途 |
|---|---|---|
aboutToAppear | 页面创建前 | 请求数据、初始化状态 |
onPageShow | 页面显示时 | 刷新数据、埋点统计 |
onPageHide | 页面隐藏时 | 暂停动画、保存临时数据 |
aboutToDisappear | 页面销毁前 | 取消订阅、清理资源 |
组件树
实际应用通常由多个组件组成树状结构:
Index (入口页面)
├── Header (自定义组件)
│ ├── Logo
│ └── Title
├── Content (自定义组件)
│ ├── Sidebar
│ └── Main
└── Footer (自定义组件)typescript
// Header.ets
@Component
export struct Header {
@Prop title: string
build() {
Row() {
Image($r('app.media.logo'))
.width(40)
.height(40)
Text(this.title)
.fontSize(20)
.margin({ left: 12 })
}
.width('100%')
.height(60)
.padding({ left: 16, right: 16 })
.backgroundColor('#F5F5F5')
}
}
// Index.ets
import { Header } from './components/Header'
@Entry
@Component
struct Index {
@State pageTitle: string = '我的应用'
build() {
Column() {
Header({ title: this.pageTitle })
// 页面内容
Column() {
Text('这是页面内容')
.fontSize(16)
}
.layoutWeight(1)
.width('100%')
// 底部
Text('© 2024')
.fontSize(12)
.fontColor('#999')
.height(40)
}
.width('100%')
.height('100%')
}
}多个应用实例
一个工程可以包含多个 UIAbility:
typescript
// module.json5 配置多个 Ability
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"mainElement": "EntryAbility"
},
{
"name": "SecondAbility",
"srcEntry": "./ets/entryability/SecondAbility.ets"
}
]
}
}启动另一个 Ability:
typescript
import { Want } from '@kit.AbilityKit'
import { common } from '@kit.AbilityKit'
async function startSecondAbility() {
const context = getContext(this) as common.UIAbilityContext
const want: Want = {
bundleName: 'com.example.myapp',
abilityName: 'SecondAbility'
}
await context.startAbility(want)
}应用配置
应用级配置 AppScope/app.json5
json5
{
"app": {
"bundleName": "com.example.myapp",
"vendor": "example",
"versionCode": 1,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name"
}
}模块级配置 module.json5
json5
{
"module": {
"name": "entry",
"type": "entry",
"deviceTypes": ["phone", "tablet"],
"mainElement": "EntryAbility",
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:app_icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
"reason": "$string:reason_internet",
"usedScene": {}
}
]
}
}重要提示
所有应用配置必须在 windowStage.loadContent() 之前完成!