前言
之前在封装图片滑动验证,还有当下的一个自适应背景颜色功能时,都需要获取到image.PixelMap对象,于是就使用了getMediaContent方法,代码如下:
TypeScript
const resourceMgr: resourceManager.ResourceManager = this.getUIContext().getHostContext()!!.resourceManager;
const fileData: Uint8Array = await resourceMgr.getMediaContent($r("app.media.banner_001").id)
const buffer = fileData.buffer as ArrayBuffer;
const imageSource: image.ImageSource = image.createImageSource(buffer);
const pixelMap: image.PixelMap = await imageSource.createPixelMap();
然而,以上的代码,却报了如下错误:
TypeScript
Failed to get media data in getMediaFunc
后续经过排查,发现了问题原因,因为我是在单独的共享包中调用的,造成了跨模块访问资源时 Context 不正确,所以导致了资源获取失败。
解决以上的问题也很简单,通过createModuleContext创建目标模块的Context,然后再获取资源管理器即可,代码如下:
TypeScript
const ctx = this.getUIContext().getHostContext()!!
const context = await application.createModuleContext(ctx, "模块名字")
当然了,还有一种解决方式,直接使用getMediaByName方法,传入资源的名字也可以。
TypeScript
const resourceMgr: resourceManager.ResourceManager = this.getUIContext().getHostContext()!!.resourceManager;
const fileData: Uint8Array = await resourceMgr.getMediaByName("banner_001")
const buffer = fileData.buffer as ArrayBuffer;
const imageSource: image.ImageSource = image.createImageSource(buffer);
const pixelMap: image.PixelMap = await imageSource.createPixelMap();
我们可以发现,很多场景下都会用到Context,比如showToast,比如获取缓存路径等等,那么什么是Context,Context在实际的开发中又是扮演着怎样的角色呢,下面,我们就来一起了解一下。
什么是Context
官方解读为:Context是应用中对象的上下文,其提供了应用的一些基础信息,例如resourceManager(资源管理)、applicationInfo(当前应用信息)、area(文件分区)等。
我们在实际的开发中,可能遇到过不同的Context,比如最常见的是UIContext,然后就是ApplicationContext,除此之外,还有很多的Context,比如基类Context、ApplicationContext、AbilityStageContext、UIAbilityContext、ExtensionContext等Context,不同类型Context的获取方式与使用场景也是不同的。
不同类型Context的继承关系如下:

不同类型Context的获取方式和使用场景如下:
| Context类型 | 说明 | 获取方式 | 使用场景 |
|---|---|---|---|
| ApplicationContext | 应用的全局上下文,提供应用级别的信息和能力。 | - 从API version 14开始,可以直接使用getApplicationContext获取。- API version 14以前版本,只能使用其他Context实例的getApplicationContext方法获取。 | - 获取当前应用的基本信息。- 获取应用级别的文件路径。- 获取和修改加密分区。- 监听应用前后台变化。 |
| AbilityStageContext | 模块级别的上下文,提供模块级别的信息和能力。 | - 如果需要获取当前AbilityStage的Context,可以直接通过AbilityStage实例获取context属性。- 如果需要获取同一应用中其他Module的Context,可以通过createModuleContext方法。 | - 获取当前模块的基本信息。- 获取模块级别的文件路径。 |
| UIAbilityContext | UIAbility组件对应的上下文,提供UIAbility对外的信息和能力。 | - 通过UIAbility实例直接获取context属性。- 在UIAbility的窗口中加载的UI组件实例,需要使用@ohos.arkui.UIContext提供的getHostContext方法。 | - 获取当前UIAbility的基本信息。- 启动其他应用或元服务、连接/断连系统应用创建的ServiceExtensionAbility等。- 销毁自身的UIAbility。 |
| ExtensionContext | ExtensionAbility组件对应的上下文,每种类型的ExtensionContext提供不同的信息和能力。 | 通过ExtensionAbility实例直接获取Context属性。 | 不同类型的ExtensionAbility对应的Context提供的能力不同。以输入法上下文InputMethodExtensionContext为例,主要提供如下能力:- 获取InputMethodExtensionAbility的基本信息。- 销毁当前输入法。 |
| UIContext | ArkUI的UI实例上下文,提供UI操作相关的能力。与上述其他类型的Context无直接关系。 | - 在UI组件内获取UIContext,直接使用组件内置的getUIContext方法。- 在存在Window实例的情况下,使用@ohos.window提供的getUIContext方法。 | 主要用于UI实例中UI相关操作,例如:- 获取当前UI实例的字体。- 显示不同类型的弹框。- 设置软键盘弹出时UI避让模式。 |
一、ApplicationContext
ApplicationContext 是应用级别的全局上下文,继承自 Context,提供了应用生命周期监听、进程管理、应用环境设置等应用级别的管控能力。有一个需要注意的点是,一个应用只有一个 ApplicationContext 实例,可以在 UIAbility、ExtensionAbility、AbilityStage 中获取。
获取方式
从 API version 14 开始,可以直接通过 application.getApplicationContext()获取,无需依赖 Context 基类;API version 14 以前,只能使用其他 Context 实例的 getApplicationContext()方法获取。
TypeScript
// 方式一:API 14+ 直接获取(推荐)
import { application, common } from "@kit.AbilityKit";
let appContext: common.ApplicationContext = application.getApplicationContext();
// 方式二:通过其他 Context 实例获取(API 9+ 通用)
// 在 UIAbility 中
import { UIAbility, common } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want): void {
let appContext: common.ApplicationContext = this.context.getApplicationContext();
}
}
核心方法与能力
| 方法/能力 | 说明 |
|---|---|
| on('abilityLifecycle') | 注册应用内组件生命周期变化监听 |
| on('environment') | 注册系统环境变化监听(语言、颜色模式等) |
| on('systemMemoryLevel') | 注册系统内存变化监听 |
| off(...) | 取消对应的事件监听 |
| getApplicationInfo() | 获取应用信息(继承自 Context) |
| getCacheDir()/ getFilesDir() | 获取应用级文件路径(继承自 Context) |
| area | 获取/设置加密分区模式 |
| setColorMode() | 设置应用颜色模式 |
| setLanguage() | 设置应用语言 |
典型使用场景
- 获取当前应用的基本信息(name、应用版本等)
- 获取应用级别的文件路径(如缓存目录、文件目录)
- 获取和修改加密分区
- 监听应用前后台变化、系统内存变化、环境变化
- 设置应用语言和颜色模式
TypeScript
import { application, common, AbilityConstant } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN: number = 0x0000;
const TAG: string = 'AppContextDemo';
// 获取应用上下文并监听生命周期
let appContext: common.ApplicationContext = application.getApplicationContext();
let abilityLifecycleCallback: AbilityLifecycleCallback = {
onAbilityCreate(ability): void {
hilog.info(DOMAIN, TAG, `Ability创建: ${ability.context.abilityInfo.name}`);
},
onAbilityForeground(ability): void {
hilog.info(DOMAIN, TAG, `Ability切到前台: ${ability.context.abilityInfo.name}`);
},
onAbilityBackground(ability): void {
hilog.info(DOMAIN, TAG, `Ability切到后台: ${ability.context.abilityInfo.name}`);
},
onAbilityDestroy(ability): void {
hilog.info(DOMAIN, TAG, `Ability销毁: ${ability.context.abilityInfo.name}`);
},
onWindowStageCreate(ability, windowStage) {
console.info(`AbilityLifecycleCallback onWindowStageCreate ability: ${ability}`);
console.info(`AbilityLifecycleCallback onWindowStageCreate windowStage: ${windowStage}`);
},
onWindowStageActive(ability, windowStage) {
console.info(`AbilityLifecycleCallback onWindowStageActive ability: ${ability}`);
console.info(`AbilityLifecycleCallback onWindowStageActive windowStage: ${windowStage}`);
},
onWindowStageInactive(ability, windowStage) {
console.info(`AbilityLifecycleCallback onWindowStageInactive ability: ${ability}`);
console.info(`AbilityLifecycleCallback onWindowStageInactive windowStage: ${windowStage}`);
},
onWindowStageDestroy(ability, windowStage) {
console.info(`AbilityLifecycleCallback onWindowStageDestroy ability: ${ability}`);
console.info(`AbilityLifecycleCallback onWindowStageDestroy windowStage: ${windowStage}`);
},
onAbilityContinue(ability) {
console.info(`AbilityLifecycleCallback onAbilityContinue ability: ${ability}`);
}
}
appContext.on('abilityLifecycle',abilityLifecycleCallback)
// 获取应用级缓存目录
let cacheDir: string = appContext.cacheDir;
hilog.info(DOMAIN, TAG, `缓存目录: ${cacheDir}`);
二、AbilityStageContext(模块上下文)
AbilityStageContext 是 AbilityStage 的上下文环境,继承自 Context,提供访问特定于 AbilityStage 的资源的能力,包括获取 AbilityStage 对应的 ModuleInfo 对象、环境变化对象****。AbilityStage 是 Module 级别的组件管理器,与 Module 一一对应,应用的 HAP/HSP 在首次加载时会创建一个 AbilityStage 实例。
获取方式
通过 AbilityStage 实例的 context属性直接获取;如果需要获取同一应用中其他 Module 的 Context,可以通过 createModuleContext方法创建。
TypeScript
import { AbilityStage } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
// 获取当前模块的 AbilityStageContext
let stageContext: common.AbilityStageContext = this.context;
// 获取当前模块信息
let moduleInfo: common.ModuleInfo = stageContext.currentHapModuleInfo;
console.info(`模块名: ${moduleInfo.moduleName}`);
}
}
核心属性与方法
| 属性/方法 | 说明 |
|---|---|
| currentHapModuleInfo | 获取当前 AbilityStage 对应的 ModuleInfo 对象 |
| getCacheDir()/ getFilesDir() | 获取模块级文件路径(继承自 Context) |
典型使用场景
- 获取当前模块的基本信息(moduleName、moduleInfo 等)
- 获取模块级别的文件路径
- 在应用启动框架(AppStartup)中作为启动任务的入参传递****
三、UIAbilityContext(UIAbility 组件上下文)
UIAbilityContext 是 UIAbility 组件的上下文,继承自 Context。每个 UIAbility 组件实例化时,系统都会自动创建对应的 UIAbilityContext。开发者可以通过它获取组件信息 AbilityInfo、应用信息 ApplicationInfo、拉起其他 UIAbility、连接系统服务、销毁 UIAbility 等****。
获取方式
在 UIAbility 中直接通过 this.context获取;在页面/组件中,需要先获取 UIContext,再通过 getHostContext()获取关联的 UIAbilityContext****。
TypeScript
// 方式一:在 UIAbility 中直接获取
import { UIAbility, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want): void {
let uiAbilityContext: common.UIAbilityContext = this.context;
console.info(`Ability名称: ${uiAbilityContext.abilityInfo.name}`);
}
}
// 方式二:在页面组件中获取(推荐方式)
@Entry
@Component
struct Index {
build() {
Column() {
Button('获取上下文')
.onClick(() => {
// 通过 getUIContext 获取 UIContext,再通过 getHostContext 获取 UIAbilityContext
let uiAbilityContext: common.UIAbilityContext =
this.getUIContext().getHostContext() as common.UIAbilityContext;
console.info(`Ability名称: ${uiAbilityContext.abilityInfo.name}`);
})
}
}
}
核心方法与能力
| 方法 | 说明 |
|---|---|
| startAbility(want) | 启动其他 UIAbility(支持 callback 和 Promise 两种方式) |
| startAbilityForResult(want) | 启动 UIAbility 并获取返回结果 |
| terminateSelf() | 销毁当前 UIAbility |
| terminateSelfWithResult() | 销毁当前 UIAbility 并返回结果 |
| connectServiceExtensionAbility(want) | 连接 ServiceExtensionAbility |
| disconnectServiceExtensionAbility(connection) | 断开 ServiceExtensionAbility 连接 |
| abilityInfo | 获取当前 UIAbility 的配置信息 |
| currentHapModuleInfo | 获取当前 HAP 模块信息 |
| config | 获取配置信息 |
典型使用场景
- 获取当前 UIAbility 的基本信息
- 启动其他应用或元服务
- 连接/断连系统应用创建的 ServiceExtensionAbility
- 销毁自身的 UIAbility
- 页面间传参与结果回传
TypeScript
import { UIAbility, Want, common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
const DOMAIN: number = 0x0000;
const TAG: string = 'UIAbilityContextDemo';
export default class EntryAbility extends UIAbility {
onCreate(want: Want): void {
let context: common.UIAbilityContext = this.context;
// 启动另一个 UIAbility
let wantInfo: Want = {
bundleName: 'com.example.demo',
abilityName: 'OtherAbility'
};
context.startAbility(wantInfo)
.then(() => {
hilog.info(DOMAIN, TAG, '启动成功');
})
.catch((err: BusinessError) => {
hilog.error(DOMAIN, TAG, `启动失败: ${err.message}`);
});
}
onBackPress(): boolean {
// 销毁当前 UIAbility
this.context.terminateSelf();
return true;
}
}
四、ExtensionContext(扩展能力上下文)
ExtensionContext 是 ExtensionAbility 组件对应的上下文,继承自 Context。每种类型的 ExtensionAbility 都有对应的 ExtensionContext 子类,提供不同的信息和能力****。ExtensionContext 本身是基类,实际使用时通常操作其子类。
常见子类
| 子类 | 对应 ExtensionAbility | 核心能力 |
|---|---|---|
| FormExtensionContext | FormExtensionAbility | 查询该扩展的FormExtensionAbility所属HAP包等信息。 |
| InputMethodExtensionContext | InputMethodExtensionAbility | 获取输入法信息、销毁当前输入法 |
| AccessibilityExtensionContext | AccessibilityExtensionAbility | 配置辅助功能、查询节点信息、手势注入 |
| PushExtensionContext | PushExtensionAbility | 访问推送扩展资源 |
| AgentExtensionContext | AgentExtensionAbility | 访问智能体配置的 AgentCard 信息 |
| AppServiceExtensionContext | AppServiceExtensionAbility | 连接/断开系统应用后台服务 |
获取方式
通过 ExtensionAbility 实例直接获取 context属性****。
TypeScript
import { FormExtensionAbility, formBindingData } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
export default class MyFormExtensionAbility extends FormExtensionAbility {
onAddForm(want: Want) {
console.info(`FormExtensionAbility onAddForm, want: ${want.abilityName}`);
let extensionContext = this.context;
let hapInfo = extensionContext.currentHapModuleInfo;
console.info(`HAP name is: ${hapInfo.name}`);
let dataObj1: Record<string, string> = {
'temperature': '11c',
'time': '11:00'
};
let obj1: formBindingData.FormBindingData = formBindingData.createFormBindingData(dataObj1);
return obj1;
}
};
典型使用场景
- 不同类型的 ExtensionAbility 对应不同的后台服务场景
- 获取当前 ExtensionAbility 的基本信息
- 启动/停止/绑定/解绑其他 Ability
- 销毁当前 ExtensionAbility
五、UIContext(UI 实例上下文)
UIContext 是 UI 实例运行环境的抽象概念,用于关联窗口与 UI 页面,管理组件、布局、动画以及交互事件等 UI 功能。UIContext 与上述四种 Context 无继承关系,它由窗口对象创建并管理,每个窗口对应一个 UIContext 实例****。
从 API version 10 开始,许多全局接口(如 @ohos.promptAction、@ohos.router、AlertDialog等)因多 UI 实例场景下上下文不明确而被废弃,需要通过 UIContext 提供的对应方法获取实例后调用****。
获取方式
UIContext 有三种获取方式****:
TypeScript
// 方式一:在自定义组件中通过内置方法获取(最常用)
@Entry
@Component
struct Index {
build() {
Column() {
Button('获取UIContext')
.onClick(() => {
let uiContext: UIContext = this.getUIContext();
})
}
}
}
// 方式二:在 UIAbility 中通过窗口获取
import { UIAbility, window } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
let uiContext: UIContext = windowStage.getMainWindowSync().getUIContext();
}
}
// 方式三:通过 UIContext 静态方法获取
import { UIContext } from '@kit.ArkUI';
let uiContext: UIContext | undefined = UIContext.getCallingScopeUIContext();
核心方法与能力
UIContext 提供了大量 UI 相关的接口,用于替代被废弃的全局接口:
| 方法 | 说明 | 替代的全局接口 |
|---|---|---|
| getPromptAction() | 获取 PromptAction 对象,用于弹窗、Toast 等 | @ohos.promptAction |
| getRouter() | 获取 Router 对象,用于页面路由 | @ohos.router |
| showAlertDialog() | 显示警告弹窗 | AlertDialog.show() |
| showActionSheet() | 显示列表选择弹窗 | ActionSheet.show() |
| getComponentUtils() | 获取 ComponentUtils 对象,用于组件坐标和尺寸信息 | @ohos.arkui.componentUtils |
| getMediaQuery() | 获取 MediaQuery 对象,用于媒体查询 | @ohos.mediaquery |
| getHostContext() | 获取关联的 UIAbilityContext 或 ExtensionContext | getContext() |
| getSharedLocalStorage() | 获取共享的 LocalStorage | - |
| runScopedTask() | 在指定 UI 上下文中执行任务 | - |
典型使用场景
- 替代全局接口进行弹窗操作(AlertDialog、ActionSheet、PromptAction)
- 页面路由跳转
- 获取组件坐标和尺寸信息
- 在页面/组件中获取关联的 UIAbilityContext
- 多 UI 实例场景下确保 UI 操作在正确的上下文中执行
TypeScript
import { UIContext, PromptAction, router } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
build() {
Column() {
// 弹窗示例
Button('显示Toast')
.onClick(() => {
let uiContext: UIContext = this.getUIContext();
let promptAction: PromptAction = uiContext.getPromptAction();
promptAction.showToast({
message: '这是一条Toast消息',
duration: 2000
});
})
// 页面路由示例
Button('跳转页面')
.onClick(() => {
let uiContext: UIContext = this.getUIContext();
let routerInstance: router.Router = uiContext.getRouter();
routerInstance.pushUrl({ url: 'pages/SecondPage' });
})
// 警告弹窗示例
Button('显示警告弹窗')
.onClick(() => {
let uiContext: UIContext = this.getUIContext();
uiContext.showAlertDialog({
title: '提示',
message: '确定要执行此操作吗?',
onConfirm: () => {
console.info('用户点击了确认');
}
});
})
// 获取 UIAbilityContext
Button('获取AbilityContext')
.onClick(() => {
let uiContext: UIContext = this.getUIContext();
let abilityContext: common.UIAbilityContext =
uiContext.getHostContext() as common.UIAbilityContext;
console.info(`包名: ${abilityContext.abilityInfo.bundleName}`);
})
}
.width('100%')
.height('100%')
}
}
AppStorage获取Context
在HarmonyOS应用开发中,工具类(非UI组件、非UIAbility的普通class)无法直接获取Context对象。标准做法是在UIAbility的生命周期回调中获取Context后,通过AppStorage.setOrCreate将其保存为全局状态数据,随后在工具类中通过AppStorage.get取出使用****。AppStorage是应用启动时创建的单例,提供应用级别的中心存储,支持主线程内多个UIAbility实例间的数据共享。
示例代码
以下示例分为两个步骤:第一步在EntryAbility中存储Context,第二步在工具类中获取Context。
步骤一:在EntryAbility的onCreate回调中存储Context
TypeScript
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 将当前UIAbility的上下文存入AppStorage,key为'appContext'
AppStorage.setOrCreate('appContext', this.context);
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index');
}
}
步骤二:在工具类中通过AppStorage获取Context
TypeScript
import { common } from '@kit.AbilityKit';
class PreferenceUtil {
// 从AppStorage中获取UIAbilityContext
static getContext(): common.UIAbilityContext {
const context = AppStorage.get<common.UIAbilityContext>('appContext');
if (!context) {
throw new Error('Context未初始化,请确认AppStorage中已存储appContext');
}
return context;
}
// 示例:使用Context获取文件路径
static getFilesDir(): string {
const context = this.getContext();
return context.filesDir;
}
}
补充说明
- 存储时机:Context应在
onCreate回调中存储,此时this.context已经可用。避免在onWindowStageCreate之前的其他阶段获取,以免Context尚未初始化****。 - 类型安全:
AppStorage.get返回值为泛型类型,使用时应明确指定泛型参数(如common.UIAbilityContext),并通过空值检查确保Context已正确存储,避免运行时异常。 - Context类型选择:根据实际需求选择存储的Context类型。
UIAbilityContext提供组件级能力(如获取filesDir、resourceManager等);若仅需应用级能力(如监听应用前后台变化),可存储ApplicationContext,通过this.context.getApplicationContext()获取****。 - 非UI场景的通用方案:此方法不仅适用于工具类,也适用于其他非ArkUI页面(如Worker线程外的纯逻辑模块)中需要访问Context的场景。Worker线程中不支持直接使用此方式,需通过消息传递将Context发送至Worker线程。
相关总结
在UI页面中,我们可以很轻松的获取到Context,但是,在工具类中如何获取呢?首先可以明确的是工具类中是无法直接获取Context的,我们可以在获取应用上下文Context后保存至AppStorage,然后通过AppStorage来获取,当然了,也可以通过别的方式,比如全局静态变量,比如一个单例工具类,等等,都是可以的。