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

HarmonyOS开发 - Ability往页面(Pages)中传递数据

       在程序中,页面之间传递数据或数据共享,可以实现页面间的平滑过渡,避免重复加载数据,提高应用的响应速度和流量度;另外,数据传递机制使得页面更容易被重用,可以通过传入不同参数,来适应不同的上下文内容,以及根据需要传递数据,实现按需加载 ,减少内存消耗和提高应用的性能等。

        这篇将通过LocalStorage、EventHub、全局变量,以及Preferences用户首选项等功能,实现Ability向页面(Pages)中传递数据。

一、页面间数据传递

        页面间跳转,可以通过router.push方法跳转到目标页面,并携带参数。代码如下:

  Column() {Image($rawfile('u27.png')).width("64vp").height("64vp")Text("门店").height("32vp").textAlign(TextAlign.Center).fontSize("16fp").fontWeight(FontWeight.Bold)}.onClick(() => {console.log('testTag')router.pushUrl({url: "pages/Stores",params: {flag: "test"}})})

        进入被分享页面,通过router.getParams(),来获取点击事件中的params带入数据。代码如下:

@Entry
@Component
struct Stores {@State productList: Array<StoresType> = [{ id: 1, name: '门店一', thumb: $rawfile('u62.png'), },{ id: 2, name: '门店二', thumb: $rawfile('u76.png') }]aboutToAppear(){const params = router.getParams()console.log('testTag', JSON.stringify(params))}// 略...
} 

        此时控制台输出结果中可以看到,被分享页面获取到了上级页面的params带入参数。如下图:

二、Ability数据传递

        在HarmonyOS中,从Ability向Page页面传递数据可以通过以下几种方式实现:

2.1、LocalStorage

        LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility实例内,在页面间共享状态,也可以通过GetShared接口,实现跨页面、UIAbility实例内共享。

        在一上篇中,已经和大家介绍了使用LocalStorage将数据传递到页面方法,地址:

HarmonyOS开发 - 餐饮APP中多门店多窗口打开实例补充-CSDN博客

        分享数据Ability代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';export default class StoreAbility extends UIAbility {// 略...onWindowStageCreate(windowStage: window.WindowStage) {// Main window is created, set main page for this abilityhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');hilog.info(0x0000, 'testTag', 'storeName:' + this.launchWant.parameters.storeName);// 通过实例new LocalStorage实例将launchWant数据传递到页面中windowStage.loadContent('pages/Index', new LocalStorage(this.launchWant.parameters), (err, data) => {if (err.code) {hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');return;}hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');});}// 略...
}

        被分享页面中接收数据,代码如下:

@Entry
@Component
struct Index {@State keyword: string = ''@State StoreName: string = '-'aboutToAppear(){const localStorage = LocalStorage.GetShared()this.StoreName = localStorage.get('storeName') as stringconsole.log('page store name:', this.StoreName)}// 略...
}

        查看控制台输出结果,如下图:

2.2、EventHub

        EventHub提供了Ability组件(UIAbility和ExtensionAbility)的事件机制,以Ability组件为中心提供了订阅、取消订阅和触发事件的数据通信能力。

2.2.1 定义Constants常量 

        在ets/common目录,再创建Constants.ets文件,用于定义和存储开发中使用的常量只读数据。这里在Constants类中定义ABILITY_WANT_DATA常量,用于定义、触发eventHub的事件名。代码如下:

/*** 常量类*/
export default class Constants {// 获取ability 中want数据static readonly ABILITY_WANT_DATA: string = 'getAbilityWantData'
}

2.2.2 定义eventHub触发事件

        在Ability中onCreate()回调函数中,定义eventHub事件,当使用emit触发事件时,执行该监听事件的回调函数,并获取到onCreate()中的want数据。代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import Constants from '../common/Constants'interface Data {launchWant: Want;
}export default class StoreAbility extends UIAbility {onCreate(want) {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');this.context.eventHub.on(Constants.ABILITY_WANT_DATA,  (data: Data) => {hilog.info(0x0000, 'testTag', 'MainAbility' + JSON.stringify(data));data.launchWant = want;})}// 略...
}

2.2.3 定义getContextWantData函数

        在ets/common目录中,创建util.ets工具包文件,并在内部定义获取数据的方法getContextWantData(),在页面文件执行时通过它获取eventHub事件中的数据。代码如下:

import Want from '@ohos.app.ability.Want'
import hilog from '@ohos.hilog';
import Constants from './Constants'class EventData {launchWant: Want | null = null
}
let that = this;export function getContextWantData(): Want {hilog.info(0x0000, 'testTag', 'Util start')let context = getContext(that);// 定义数据bus事件let data: EventData = new EventData();// 触发eventHub事件,请求数据context.eventHub.emit(Constants.ABILITY_WANT_DATA, data);hilog.info(0x0000, 'testTag', 'Util want ' + JSON.stringify(data.launchWant as Want));return data.launchWant as Want;
}

2.2.4 页面获取数据

        页面中引入getContextWantData()函数,在struct外部分获取wantData数据,在aboutToAppear()回调函数中输出结果参数并查询获取的结果。

import Header from '../components/Header'// 略...import { getContextWantData } from '../common/utils'
const wantData = getContextWantData()@Entry
@Component
struct Index {@State keyword: string = ''@State StoreName: string = '-'aboutToAppear(){const params = wantData.parametersthis.StoreName = params('storeName')console.log('testTag want parameters', JSON.stringify(params))}// 略...
}  

        使用此方法,同样可以实现数据共享和传递。并且,从下图中可以看出,各自执行的先后顺序。

如上图可知,程序中各自执行流程:

  1. Ability中的onCreate()回调函数先执行于页面,所以在触发onCreate()回调函数时,定义eventHub事件和回调函数,等待页面中触发emit事件获取数据。
  2. 当加载页面时,执行getContextWantData()函数,触发了emit事件得到了onCreate()中eventHub回调函数响应,并获取回调函数中的want数据,将其通过return返回输出到页面中。
  3. 在aboutToAppear()回调函数执行时,将获取到的want数据绑定到当前页面的状态变量StoreName上,使数据向下传递到Header组件中并在界面中显示结果(门店名称)。

2.3、使用全局变量

        可以将数据存储在globalThis对象上,然后在Page页面中直接访问这些数据。这个方法更为直接,且全局共享。

2.3.1 定义GlobalThis类

        首先在ets/common目录中创建globalThis.ets文件,代码如下:


import Want from '@ohos.app.ability.Want'
class GlobalThis {launchWant: Want
}
// 单例模式,全局共享
const globalData = new GlobalThis()export default globalData

2.3.2 Ability中绑定

        在Ability中引入globaData实例,并在onCreate()函数执行时,将回调函数中获取到的want数据绑定到globalData实例的launchWant变量上。代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import globalData from '../common/globalThis'export default class StoreAbility extends UIAbility {onCreate(want) {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');// 获取数据,并绑定在全局变量上globalData.launchWant = want;}// 略...
}

2.3.3 页面中获取

        在页面中同样是直接引入globalData实例,在aboutToAppear()回调函数执行时绑定门店名称信息,并在控制台输出结果。

import Header from '../components/Header'// 略...import globalData from '../common/globalThis'@Entry
@Component
struct Index {@State keyword: string = ''@State StoreName: string = '-'aboutToAppear(){const params = globalData.launchWant.parametersthis.StoreName = params('storeName')console.log('testTag globalData launchWant', JSON.stringify(globalData.launchWant.parameters))}

        控制台输出结果如下图:

2.4、Preferences用户首选项

        通过Preferences用户首选项实现数据持久化,这在之前写过一篇文档中介绍了Preferences用户首选项功能,并使用它封装了一个LocalStorage本地持久化数据功能。

地址1:HarmonyOS开发 - 本地持久化之实现LocalStorage实例_localstorage需要定义吗-CSDN博客

地址2:HarmonyOS开发 - 本地持久化之实现LocalStorage支持多实例-CSDN博客

2.4.1  LocalStorageMulti本地持久化

        这里就直接贴代码了,拷到项目的ets/common目录、命令为localStorageMulti.ets,代码如下:

import common from '@ohos.app.ability.common'
import preferences from '@ohos.data.preferences'const isJsonObject = (value: string) : boolean => {try {const parseStr = JSON.parse(value)return 'object' === typeof parseStr && null !== parseStr} catch (e) {console.log('testTag', e)return false}
}// 定义存储值类型
type valueType = string | number | boolean
// 定义json对象存储类型
type dataType = { value: valueType | object, expire: number }/*** 定义LocalStorage类*/
export class MyLocalStorage {private preference: preferences.Preferences // 用户首选项实例对象// 定义多Preferences实例 存储变量private static multiPreferences: Map<string, MyLocalStorage> = new Map()// preferences加载成功回调函数public preferenceSuccess: Function = () => {}/*** 创建多实例* @param context*/static multiInstance(context?: common.UIAbilityContext): MyLocalStorage {const name = context.abilityInfo.name// 如果存在该实例,则直接返回if(MyLocalStorage.multiPreferences.has(name)) {console.log('testTag context.abilityInfo.name update', name)return MyLocalStorage.multiPreferences.get(name)}// 如果不存在,则创建实例else {console.log('testTag context.abilityInfo.name create', name)const instance = new MyLocalStorage()     // 实例LocalStorage对象instance.initial(context)               // 初始化Preferences实例// 存储LocalStorage对象MyLocalStorage.multiPreferences.set(name, instance)// 返回实例对象return instance}}// 定义初始化函数initial(context: common.UIAbilityContext): void {// 这里将UIAbility中应用上下文的name作用为实例名称,即该项目的ApplicationAbility或ProductAbilitypreferences.getPreferences(context, context.abilityInfo.name).then(preference => {this.preference = preferenceif('function' === typeof this.preferenceSuccess) this.preferenceSuccess()console.log('testTag', 'success~')}).catch(e => {console.log('testTag error', e)})}/*** 定义增加函数* @param key* @param value* @param expire*/put(key: string, value: valueType | object, expire?: Date): void {// 定义存储Json格式对象const data : dataType = {value,      // 存储内容expire : (expire ? expire.getTime() : -1)   // 如果失效时间存在,将其转换为时间戳,否则传入-1}let dataStr: string = '';try {dataStr = JSON.stringify(data)    // 当数据转换成功,将其存储console.log('testTag', dataStr)} catch (e) {console.log('testTag error', e)return}this.preference.put(key, dataStr).then(() => this.preference.flush()).catch(e => {console.log('testTag error', e)})}/*** 定义获取对应key数据* @param key*/async getValue(key: string): Promise<valueType | object> {// 首页判断key值是否存在,不存在返回空if(!this.preference.has(key)) {return Promise.resolve(null)}let value = (await this.preference.get(key, '')) as valueType// 判断如果为字符串类型数据,并且为JSON对象格式数据,将其转换为对象if('string' === typeof value && isJsonObject(value)) {try {const data: dataType = JSON.parse(value)console.log('testTag', data.expire, Date.now(), data.expire < Date.now())// 如果当前存储内容无时效性,或者在时效期内,都直接返回if(data.expire === -1 || data.expire > Date.now()) {return Promise.resolve(data.value)}// 如果已失效,将其信息删除else {this.preference.delete(key)}} catch (e) {console.log('testTag error', e)return Promise.resolve(null)      // 如果转换出错,返回null}}// 通过Promise异步回调将结果返回(如果内容不为JSON格式对象,或者过了时效期,返回null)return Promise.resolve(null)}/*** 更新数据* @param key* @param value*/async update(key: string, value: valueType){try {const preValue = await this.getValue(key)if(preValue != value) {this.put(key, value)}} catch (e) {console.log('testTag error', e)}}/*** 定义移除函数* @param key*/remove(key: string): void {this.preference.delete(key).then(() => this.preference.flush()).catch(e => {console.log('testTag error', e)})}/*** 定义清除所有数据函数*/clearAll(): void {this.preference.clear().then(() => this.preference.flush()).catch(e => {console.log('testTag error', e)})}
}
/*** 实例LocalStorage*/
const myLocalStorage = new MyLocalStorage()/*** 导出localStorage单例对象*/
export default myLocalStorage as MyLocalStorage

2.4.2 Ability中初始化并存储数据

        在onCreate()回调函数中,获取MyLocalStorage实例对象,并且等待myStore.preferenceSuccess()执行回调时,表示Preferences实例已加载完成,可以执行存取操作了。代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import { MyLocalStorage } from '../common/LocalStorageMulti'export default class StoreAbility extends UIAbility {onCreate(want) {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');// 通过本地存储,存储Want数据const myStore=  MyLocalStorage.multiInstance(this.context)hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate' + JSON.stringify((want.parameters)));// 在Preferences首选项加载成功后执行myStore.preferenceSuccess = () => {myStore.put('want', want.parameters)}}// 略...
}

2.4.3 页面中获取持久化数据

        在页面中通过MyLocalStorage对象完成want数据获取,首先是将MyLocalStorage实例本地化,方便后续使用,再通过异步完成数据获取工作,并且将结果输出到控制台上。代码如下:

import Header from '../components/Header'// 略...import { MyLocalStorage } from '../common/LocalStorageMulti'
import common from '@ohos.app.ability.common'@Entry
@Component
struct Index {@State keyword: string = ''@State StoreName: string = '-'private myLocalStorage: MyLocalStorageasync aboutToAppear(){this.myLocalStorage = MyLocalStorage.multiInstance(getContext(this) as common.UIAbilityContext)// 获取Ability中本地化存储的Want参数信息const wantData = await this.myLocalStorage.getValue('want')// 将storeName赋值给状态变量this.StoreName = wantData.storeNameconsole.log('testTag myLocalStorage', JSON.stringify(wantData))}// 略...
}

        控制台结果如下图:

        在HarmonyOS中,数据传递和共享的方式多种多样,每种方式都有其适用的场景和优势。选择合适的数据传递和共享方式,可以提高应用的性能、可维护性和用户体验。根据功能场景需求,选择一种较为合适的即可。


http://www.mrgr.cn/news/66317.html

相关文章:

  • 第二届新生程序设计竞赛热身赛(C语言)
  • 七牛云OSS的使用
  • Element Plus暗黑模式及模式自由切换
  • oracle-函数-NULLIF (expr1, expr2)的妙用
  • 【自用】fastapi学习记录--请求和参数
  • GO语言基础(三)
  • 年薪平均几十万?!哪些行业的软件测试工程师需求量大,前景好?
  • ubuntu工具 -- ubuntu服务器临时没有网络,急需联网下载东西怎么办? 使用手机提供网络
  • @ApiOperation(“修改帐号状态“)详细解释一下以上代码
  • 视频监控接入平台功能:视频平台系统的硬件性能直观显示和系统软件运行情况和状态显示
  • 【初阶数据结构篇】链式结构二叉树(续)
  • vue组件在项目中的常用业务逻辑(3)
  • 11.5 dmy NOIP模拟赛DAY4 总结
  • operator[ ]和迭代器,auto,for流,reserve
  • MySQL初学之旅(1)配置与基础操作
  • 数据库基础(4) . 数据库结构
  • Unity自动打包——Shell交互
  • 【C/C++】memcpy函数的使用
  • centos 6 yum安装 rabbitmq
  • 软硬链接与动静态库
  • 无需懂代码!用AI工具Bolt一键生成网站的入门指南!
  • RTX 50很快就能见面!3个月内 全家登场
  • 基于 JAVASSM(Java + Spring + Spring MVC + MyBatis)框架开发一个医院挂号系统
  • 90%会展主办方都会用的6款数字化工具
  • 基于 JAVASSM(Java + Spring + Spring MVC + MyBatis)框架开发一个九宫格日志系统
  • Flutter 正在切换成 Monorepo 和支持 workspaces