【HarmonyOS NEXT】应用上下文Context

一、背景

在鸿蒙开发中,应用上下文Context是一个很重要的知识点,特此整理下加深印象

二、概念

Context是应用的核心上下文对象,提供基础信息与能力。

2.1 核心理解 -

身份凭证:标识应用身份信息(包名、版本、权限等)

能力入口:提供访问系统服务和资源的统一接口

通信桥梁:连接应用内部组件与外部系统

2.2 类型体系

Context
├── ApplicationContext (应用级上下文)
├── UIAbilityContext (UIAbility上下文)
├── ExtensionContext (扩展能力上下文)
└── FormExtensionContext (卡片上下文)

2.3 持有关系

- 每个UIAbility实例持有自己的UIAbilityContext

- ApplicationContext由整个应用共享

- 组件通过getContext()获取所属Ability的上下文

不同类型Context的继承关系如下:

不同类型Context的持有关系如下:

三、为什么需要 Context

3.1、解决的核心问题

在没有Context的情况下,面临的问题

问题解决前解决后
资源访问混乱每个组件自行管理资源,容易冲突统一资源管理,安全隔离
组件通信困难组件间直接依赖,耦合度高通过Context解耦,标准化通信
权限管理分散权限检查逻辑重复,安全性差集中权限管理,安全可控
生命周期复杂各组件自行管理状态,难以维护统一生命周期管理

简言之,主要是为了简化数据共享和系统交互

四、Context 的主要作用

作用类别具体功能
资源管理获取 ResourceManager、访问应用资源
组件启动启动 Ability、Service、DataAbility
文件操作获取应用文件目录、缓存目录
权限管理权限申请和验证
系统服务访问窗口管理、通知服务等
配置信息获取应用包名、版本信息等

五、Context使用场景

场景1、资源管理能力

5.1.1、同步获取格式化字符串

解决的问题:

  • 字符串格式化:处理带占位符的字符串资源(如:"欢迎%s,今天是第%d天")

  • 同步执行:在需要立即获取字符串值的场景使用

  • 类型安全:参数类型明确为 string | number

import { common } from "@kit.AbilityKit";

export function getStringFromResourceSync(resource: Resource, ...args: Array<string | number>): string {
  const context = getContext() as common.UIAbilityContext;
  return context.resourceManager.getStringSync(resource.id, ...args)
}

使用场景:

import { getStringFromResourceSync } from '../view/utils'

@Entry
@Component
struct Index {
  build() {
    // 资源定义:app.string.welcome_message = "欢迎%s,您是第%d位访客"
    Text(getStringFromResourceSync($r('app.string.welcome_message'), '张三', 5))
    // 结果: "欢迎张三,您是第5位访客"
  }
}

5.1.2、同步获取普通字符串

解决的问题:

  • 简单字符串访问:不需要格式化的普通字符串资源

  • 零延迟获取:同步调用,立即返回值

  • 错误传播:如果资源不存在会直接抛出异常

export function getStringResourceSync(resource: Resource) {
  const context = getContext() as common.UIAbilityContext;
  return context.resourceManager.getStringSync(resource)
}

使用场景:

import { getStringResourceSync } from '../view/utils'
import { router } from '@kit.ArkUI'

@Entry
@Component
struct Index {
  build() {
    Column({ space: 20 }) {
      Button('点击')
        .onClick(() => {
          router.pushUrl({
            url: 'pages/mine',
            params: {
              key: getStringResourceSync($r('app.string.scroll_open_accurate_search'))
            }
          })
        })
    }
  }
}

说明:

此处是将 Resource 对象转换为实际的 string 值,在需要传递字符串值的场景(路由、API、配置等)中必不可少

场景二、组件启动与管理

// 启动其他Ability
let want: Want = {
  bundleName: 'com.example.app',
  abilityName: 'DetailAbility',
  parameters: { id: 123 }
};
await context.startAbility(want);

// 启动服务
await context.startServiceExtensionAbility(want);

场景三、权限管理

具体能力:

  • 权限申请abilityAccessCtrl.AtManager.requestPermissionsFromUser()

  • 上下文获取:通过UI组件的上下文获取UIAbilityContext

  • 用户交互:显示系统原生的权限申请对话框

前提:在 module.json5 中进行权限声明

动态申请权限:

import { abilityAccessCtrl, common, PermissionRequestResult, Permissions } from '@kit.AbilityKit'
import { BusinessError } from '@kit.BasicServicesKit'

@Entry
@Component
struct Index {
  build() {
    Column({ space: 20 }) {
      Button('点击获取位置权限')
        .onClick(() => {
          this.goPermission()
        })
    }
  }

  goPermission() {
    // 位置权限申请
    const locationPermissions: Array<Permissions> = [
      'ohos.permission.APPROXIMATELY_LOCATION',
      'ohos.permission.LOCATION',
    ];
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
    let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    atManager.requestPermissionsFromUser(context, locationPermissions,
      (err: BusinessError, data: PermissionRequestResult) => {
        if (err) {
          console.error(`requestPermissionsFromUser fail, code: ${err.code}, message: ${err.message}`);
        } else {
          console.info(`requestPermissionsFromUser success, result: ${data}`);
          console.info('requestPermissionsFromUser data permissions:' + data.permissions);
          console.info('requestPermissionsFromUser data authResults:' + data.authResults);
          console.info('requestPermissionsFromUser data dialogShownResults:' + data.dialogShownResults);
        }
      })
  }
}

场景四、系统服务访问

在窗口设置沉浸式页面

使用Window.setWindowLayoutFullScreen()方法设置窗口为全屏模式。

import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';


export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage) {
    // 1.Get the main window of the application.
    let windowClass: window.Window | undefined = undefined;
    windowStage.getMainWindow().then(windowClass => {
      console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(windowClass));
      // 2.Set the window to full screen to achieve immersive effects.
      windowClass.setWindowLayoutFullScreen(true).then(() => {
        console.info('Succeeded in setting the window layout to full-screen mode.');
      }).catch((e: BusinessError) => {
        console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(e));
      })
    }).catch((err: BusinessError) => {
      console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));
    })
    // 3.Load the corresponding target page for the immersive window.
    windowStage.loadContent("pages/Index", (err) => {
      if (err.code) {
        console.error('Failed to load the content. Cause:' + JSON.stringify(err));
        return;
      }
      console.info('Succeeded in loading the content.');
    });
  }
};

场景五、事件通信

@Entry
@Component
struct Index {
  aboutToDisappear(): void {
    //组件销毁时取消事件订阅
    getContext().eventHub.off('dataUpdate')
  }

  build() {
    Column({ space: 20 }) {
      Button('点击')
        .onClick(() => {
          //发送事件
          getContext().eventHub.emit('dataUpdate', (data: string) => {
            console.log('收到数据更新:', data);
          });
        })
    }
  }
}

六、Context 解决的问题

6.1、架构层面

通过Context实现组件间安全通信

统一资源调度,避免冲突

标准化组件生命周期

6.2、开发效率与安全上

通用能力封装,减少重复代码

安全数据共享机制

组件访问权限验证

<think>好的,我现在需要解决用户的问题:如何在HarmonyOS Next中查看本地关系型数据库。首先,我得回忆一下HarmonyOS的数据库管理方式。HarmonyOS主要使用关系型数据库(Relational Database,RDB)来存储本地结构化数据,这通常通过RDB Store API来操作。 用户提到的是“查看”数据库,这可能包括浏览数据、查询表结构或者检查数据库内容。根据之前的知识,HarmonyOS应用数据是沙盒化的,每个应用的数据库存储在各自的沙盒目录中,不能直接用文件管理器查看。因此,可能需要通过代码或者开发工具来实现。 首先,我应该考虑使用HarmonyOS提供的API来访问数据库。例如,通过RdbStore接口执行查询语句,获取数据并展示在应用界面上。另外,开发调试阶段可能需要使用日志输出或者开发者工具中的数据库查看功能。但不确定HarmonyOS Next是否有类似Android的Device File Explorer或者数据库调试工具。 接下来,我需要查阅相关的文档或开发者资源。根据引用中的内容,虽然没有直接提到HarmonyOS的数据库查看方法,但可以参考通用的移动应用数据库管理思路。例如,在代码中实现查询并输出结果,或者将数据库文件导出到电脑上用第三方工具查看。 另外,HarmonyOS Next可能集成了新的开发者工具,比如DevEco Studio,可能提供数据库浏览功能。需要确认是否有这样的功能,或者是否需要通过adb-like的命令来访问设备文件系统,进而导出数据库文件。 可能的步骤包括: 1. 在应用中使用RDB API查询数据库并显示结果。 2. 导出数据库文件到本地,使用SQLite工具查看(因为HarmonyOS的RDB基于SQLite)。 3. 利用DevEco Studio的数据库查看插件或功能。 需要确保回答覆盖这些方法,并且步骤清晰,适合开发者操作。同时注意代码示例的正确性,比如创建RdbStore实例、执行查询等。另外,用户权限问题也很重要,应用必须有访问数据库的权限,且数据库文件路径正确。 可能遇到的问题包括:如何获取数据库文件路径?如何在没有root权限的情况下导出数据库?这时候可能需要依赖应用的沙盒目录,通过上下文获取数据库路径,然后使用文件管理API导出。或者,在模拟器中调试时直接访问该路径。 总结下来,回答应该分步骤说明,包括代码查询、导出数据库和使用工具查看等方法,并引用相关文档或API指南。</think>在HarmonyOS Next中查看本地关系型数据库,可以通过以下步骤实现: ### 1. 使用RDB API查询数据库 HarmonyOS的关系型数据库(RDB)基于SQLite封装,可通过`RdbStore`接口操作: ```typescript import relationalStore from '@ohos.data.relationalStore'; // 创建RdbStore实例 let config = { name: 'MyDatabase.db', // 数据库名称 securityLevel: relationalStore.SecurityLevel.S1 // 安全级别 } let predicates = new relationalStore.RdbPredicates('TABLE_NAME') // 替换为实际表名 relationalStore.getRdbStore(this.context, config, (err, store) => { if (err) { console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`); return; } // 执行查询 store.query(predicates, ['*'], (err, resultSet) => { if (resultSet.rowCount > 0) { resultSet.goToFirstRow() do { let data = resultSet.getRow() // 获取当前行数据 console.log(JSON.stringify(data)) // 输出到日志 } while(resultSet.goToNextRow()) } }) }) ``` 此代码可查询指定表的所有数据并输出到日志[^1]。 ### 2. 导出数据库文件 通过应用沙盒路径获取数据库文件: ```typescript import fileio from '@ohos.fileio'; // 获取数据库文件路径 let dbPath = this.context.databaseDir + '/MyDatabase.db' // 导出到公共目录 fileio.copyFileSync(dbPath, '/data/storage/el2/base/haps/entry/files/exported.db') ``` 导出后可通过ADB命令拉取文件: ```shell adb pull /data/app/.../exported.db ~/Desktop/ ``` 然后用SQLite工具(如DB Browser for SQLite)打开查看完整数据[^3]。 ### 3. 使用DevEco Studio调试 在开发者模式下: 1. 连接设备并打开`DevEco Studio` 2. 进入`Tools > Device Manager` 3. 选择目标设备后,打开`File Viewer` 4. 导航到路径`/data/app/.../databases/` 5. 导出`.db`文件进行查看 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值