鸿蒙HarmonyOS实战-Stage模型(UIAbility组件)_error module-abilities-srcentry ‘(1)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img

img
img
htt

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

]

}
}


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7ad5be5ab0004544ac7429f172bbaa10.png)


#### 🦋3.3 specified(指定实例模式)


指定实例模式(specified instance pattern)用于限定一个类只能有固定数目的实例。在这种模式中,类的实例被限制为预先定义的数量,且这些实例在运行时不能被创建或销毁。


指定实例模式常用于需要限制某个类的实例数量的场景。例如,一个数据库连接池的实现可以使用指定实例模式来限制连接的数量,确保不会创建过多的连接。另一个例子是线程池,可以使用指定实例模式来限制线程的数量。


在指定实例模式中,通常会维护一个内部的实例列表,来跟踪已经创建的实例。当需要获取一个实例时,会首先检查这个列表,如果列表中已经有足够的实例,则直接返回一个实例给调用者。如果列表中没有足够的实例,则根据需求创建新的实例,并添加到列表中。当实例不再需要时,通常会将其从列表中移除,以便可以继续创建新的实例。


指定实例模式可以有效地控制类的实例数量,避免了资源的浪费和过度创建实例的问题。然而,由于实例数量是固定的,所以可能会出现竞争条件和资源瓶颈的问题,需要进行合理的设计和调优。


指定实例模式配置如下:



{
“module”: {
// …
“abilities”: [
{
“launchType”: “specified”,
// …
}
]
}
}


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/61d696f003f84477b46a16766d3dfb8b.png)


案例说明:


例如有两个UIAbility:EntryAbility和FuncAbility,FuncAbility配置为specified启动模式,需要从EntryAbility的页面中启动FuncAbility。


1、在FuncAbility中,将module.json5配置文件的"launchType"字段配置为"specified"。



{
“module”: {
// …
“abilities”: [
{
“launchType”: “specified”,
// …
}
]
}
}


2、在EntryAbility中,调用startAbility()方法时,在want参数中,增加一个自定义参数来区别UIAbility实例,例如增加一个"instanceKey"自定义参数。



// 在启动指定实例模式的UIAbility时,给每一个UIAbility实例配置一个独立的Key标识
// 例如在文档使用场景中,可以用文档路径作为Key标识
function getInstance() {
// …
}

let want = {
deviceId: ‘’, // deviceId为空表示本设备
bundleName: ‘com.example.myapplication’,
abilityName: ‘FuncAbility’,
moduleName: ‘module1’, // moduleName非必选
parameters: { // 自定义信息
instanceKey: getInstance(),
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(want).then(() => {
// …
}).catch((err) => {
// …
})


3、获取UIAbility参数



import AbilityStage from ‘@ohos.app.ability.AbilityStage’;

export default class MyAbilityStage extends AbilityStage {
onAcceptWant(want): string {
// 在被调用方的AbilityStage中,针对启动模式为specified的UIAbility返回一个UIAbility实例对应的一个Key值
// 当前示例指的是module1 Module的FuncAbility
if (want.abilityName === ‘FuncAbility’) {
// 返回的字符串Key标识为自定义拼接的字符串内容
return ControlModule_EntryAbilityInstance_${want.parameters.instanceKey};
}

    return '';
}

}


### 4.基本用法


#### 🦋4.1 指定UIAbility的启动页面



import UIAbility from ‘@ohos.app.ability.UIAbility’;
import Window from ‘@ohos.window’;

export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: Window.WindowStage) {
// Main window is created, set main page for this ability
windowStage.loadContent(‘pages/Index’, (err, data) => {
// …
});
}

// ...

}


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/45beb90de765483aa64e776ca20e048d.png)


#### 🦋4.2 获取UIAbility的上下文信息


通过UIAbilityContext可以获取UIAbility的相关配置信息,包括包代码路径、Bundle名称、Ability名称和应用程序需要的环境状态等属性信息。此外,还可以使用UIAbilityContext提供的方法来操作UIAbility实例,例如startAbility()、connectServiceExtensionAbility()、terminateSelf()等。



import UIAbility from ‘@ohos.app.ability.UIAbility’;

export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// 获取UIAbility实例的上下文
let context = this.context;

    // ...
}

}


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/32075aa133df4011aafa9bacf4830796.png)  
 在页面获取



import common from ‘@ohos.app.ability.common’;

@Entry
@Component
struct Index {
private context = getContext(this) as common.UIAbilityContext;

startAbilityTest() {
let want = {
// Want参数信息
};
this.context.startAbility(want);
}

// 页面展示
build() {
// …
}
}


### 5.UIAbility组件与UI的数据同步


主要有两种方式:




| 方式 | 描述 |
| --- | --- |
| EventHub | 基于发布订阅模式来实现,事件需要先订阅后发布,订阅者收到消息后进行处理。 |
| globalThis | ArkTS引擎实例内部的一个全局对象,在ArkTS引擎实例内部都能访问。 |


#### 🦋5.1 使用EventHub进行数据通信


1、注册事件,使用其中一种即可



import UIAbility from ‘@ohos.app.ability.UIAbility’;

const TAG: string = ‘[Example].[Entry].[EntryAbility]’;

export default class EntryAbility extends UIAbility {
func1(…data) {
// 触发事件,完成相应的业务操作
console.info(TAG, '1. ’ + JSON.stringify(data));
}

onCreate(want, launch) {
    // 获取eventHub
    let eventhub = this.context.eventHub;
    // 执行订阅操作
    eventhub.on('event1', this.func1);
    eventhub.on('event1', (...data) => {
        // 触发事件,完成相应的业务操作
        console.info(TAG, '2. ' + JSON.stringify(data));
    });
}

}


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a041a7881f4240ea8b7c9ce1099fd1ca.png)


2、触发事件



import common from ‘@ohos.app.ability.common’;

@Entry
@Component
struct Index {
private context = getContext(this) as common.UIAbilityContext;

eventHubFunc() {
// 不带参数触发自定义“event1”事件
this.context.eventHub.emit(‘event1’);
// 带1个参数触发自定义“event1”事件
this.context.eventHub.emit(‘event1’, 1);
// 带2个参数触发自定义“event1”事件
this.context.eventHub.emit(‘event1’, 2, ‘test’);
// 开发者可以根据实际的业务场景设计事件传递的参数
}

// 页面展示
build() {
// …
}
}


3、取消事件



// context为UIAbility实例的AbilityContext
this.context.eventHub.off(‘event1’);


#### 🦋5.2 使用globalThis进行数据同步


在HarmonyOS中,globalThis是一个全局对象,它提供了一个统一的方式来访问不同环境下的全局对象。在HarmonyOS中,globalThis可以用来访问当前运行环境中的全局对象,可以是浏览器环境中的window对象,也可以是Node.js环境中的global对象。


使用globalThis可以方便地在不同环境下编写通用的代码,不需要针对不同的环境做特殊的处理。例如,可以使用globalThis来访问全局的console对象,无论在浏览器环境还是Node.js环境中,都可以使用console.log()来输出日志。


虽然globalThis提供了一种通用的访问全局对象的方式,但在实际编程中还是建议根据具体的环境来使用相应的全局对象。  
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/98e53ff1bb6b4ca5aba81d17e4a104b7.png)


##### ☀️5.2.1 UIAbility和Page之间使用globalThis


1、注册



import UIAbility from ‘@ohos.app.ability.UIAbility’

export default class EntryAbility extends UIAbility {
onCreate(want, launch) {
globalThis.entryAbilityWant = want;
// …
}

// ...

}


2、获取



let entryAbilityWant;

@Entry
@Component
struct Index {
aboutToAppear() {
entryAbilityWant = globalThis.entryAbilityWant;
}

// 页面展示
build() {
// …
}
}


##### ☀️5.2.2 UIAbility和UIAbility之间使用globalThis


1、注册



import UIAbility from ‘@ohos.app.ability.UIAbility’

export default class AbilityA extends UIAbility {
onCreate(want, launch) {
globalThis.entryAbilityStr = ‘AbilityA’; // AbilityA存放字符串“AbilityA”到globalThis
// …
}
}


2、获取



import UIAbility from ‘@ohos.app.ability.UIAbility’

export default class AbilityB extends UIAbility {
onCreate(want, launch) {
// AbilityB从globalThis读取name并输出
console.info('name from entryAbilityStr: ’ + globalThis.entryAbilityStr);
// …
}
}


##### ☀️5.2.3 globalThis使用的注意事项


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/98ad77e8ba4a44c3ab37b045f1c6918b.png)


案例:


1、在AbilityA文件中使用globalThis中存放了UIAbilityContext。



import UIAbility from ‘@ohos.app.ability.UIAbility’

export default class AbilityA extends UIAbility {
onCreate(want, launch) {
globalThis.context = this.context; // AbilityA存放context到globalThis
// …
}
}


2、在AbilityA的页面中获取该UIAbilityContext并进行使用。使用完成后将AbilityA实例切换至后台。



@Entry
@Component
struct Index {
onPageShow() {
let ctx = globalThis.context; // 页面中从globalThis中取出context并使用
let permissions = [‘com.example.permission’]
ctx.requestPermissionsFromUser(permissions,(result) => {
// …
});
}
// 页面展示
build() {
// …
}
}


3、在AbilityB文件中使用globalThis中存放了UIAbilityContext,并且命名为相同的名称。



import UIAbility from ‘@ohos.app.ability.UIAbility’

export default class AbilityB extends UIAbility {
onCreate(want, launch) {
// AbilityB覆盖了AbilityA在globalThis中存放的context
globalThis.context = this.context;
// …
}
}


4、在AbilityB的页面中获取该UIAbilityContext并进行使用。此时获取到的globalThis.context已经表示为AbilityB中赋值的UIAbilityContext内容。



@Entry
@Component
struct Index {
onPageShow() {
let ctx = globalThis.context; // Page中从globalThis中取出context并使用
let permissions = [‘com.example.permission’]
ctx.requestPermissionsFromUser(permissions,(result) => {
console.info(‘requestPermissionsFromUser result:’ + JSON.stringify(result));
});
}
// 页面展示
build() {
// …
}
}


5、在AbilityB实例切换至后台,将AbilityA实例从后台切换回到前台。此时AbilityA的onCreate生命周期不会再次进入。



import UIAbility from ‘@ohos.app.ability.UIAbility’

export default class AbilityA extends UIAbility {
onCreate(want, launch) { // AbilityA从后台进入前台,不会再走这个生命周期
globalThis.context = this.context;
// …
}
}


6、在AbilityA的页面再次回到前台时,其获取到的globalThis.context表示的为AbilityB的UIAbilityContext,而不是AbilityA的UIAbilityContext,在AbilityA的页面中使用则会出错。



@Entry
@Component
struct Index {
onPageShow() {
let ctx = globalThis.context; // 这时候globalThis中的context是AbilityB的context
let permissions=[‘com.example.permission’];
ctx.requestPermissionsFromUser(permissions,(result) => { // 使用这个对象就会导致进程崩溃
console.info(‘requestPermissionsFromUser result:’ + JSON.stringify(result));
});
}
// 页面展示
build() {
// …
}
}


### 6.UIAbility组件间交互(设备内)


#### 🦋6.1 启动应用内的UIAbility


1、启动方



let wantInfo = {
deviceId: ‘’, // deviceId为空表示本设备
bundleName: ‘com.example.myapplication’,
abilityName: ‘FuncAbility’,
moduleName: ‘module1’, // moduleName非必选
parameters: { // 自定义信息
info: ‘来自EntryAbility Index页面’,
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// …
}).catch((err) => {
// …
})


2、接受方



import UIAbility from ‘@ohos.app.ability.UIAbility’;
import Window from ‘@ohos.window’;

export default class FuncAbility extends UIAbility {
onCreate(want, launchParam) {
// 接收调用方UIAbility传过来的参数
let funcAbilityWant = want;
let info = funcAbilityWant?.parameters?.info;
// …
}
}


在FuncAbility业务完成之后,如需要停止当前UIAbility实例,在FuncAbility中通过调用terminateSelf()方法实现。



// context为需要停止的UIAbility实例的AbilityContext
this.context.terminateSelf((err) => {
// …
});


#### 🦋6.2 启动应用内的UIAbility并获取返回结果


1、启动方



let wantInfo = {
deviceId: ‘’, // deviceId为空表示本设备
bundleName: ‘com.example.myapplication’,
abilityName: ‘FuncAbility’,
moduleName: ‘module1’, // moduleName非必选
parameters: { // 自定义信息
info: ‘来自EntryAbility Index页面’,
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(wantInfo).then((data) => {
// …
}).catch((err) => {
// …
})


2、接受方



const RESULT_CODE: number = 1001;
let abilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: ‘com.example.myapplication’,
abilityName: ‘FuncAbility’,
moduleName: ‘module1’,
parameters: {
info: ‘来自FuncAbility Index页面’,
},
},
}
// context为被调用方UIAbility的AbilityContext
this.context.terminateSelfWithResult(abilityResult, (err) => {
// …
});


3、获取接受方回调参数



const RESULT_CODE: number = 1001;

// …

// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被调用方UIAbility返回的信息
let info = data.want?.parameters?.info;
// …
}
}).catch((err) => {
// …
})


#### 🦋6.3 启动其他应用的UIAbility


1、接受方配置信息



{
“module”: {
“abilities”: [
{
// …
“skills”: [
{
“entities”: [
// …
“entity.system.default”
],
“actions”: [
// …
“ohos.want.action.viewData”
]
}
]
}
]
}
}


2、启动方



let wantInfo = {
deviceId: ‘’, // deviceId为空表示本设备
// 如果希望隐式仅在特定的捆绑包中进行查询,请取消下面的注释。
// bundleName: ‘com.example.myapplication’,
action: ‘ohos.want.action.viewData’,
// entities可以被省略。
entities: [‘entity.system.default’],
}

// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// …
}).catch((err) => {
// …
})


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/741073a8bc9c462ca685d12f7741f9b2.png)


完成后不要忘了,停止



// context为需要停止的UIAbility实例的AbilityContext
this.context.terminateSelf((err) => {
// …
});


#### 🦋6.4 启动其他应用的UIAbility并获取返回结果


1、接受方配置信息



{
“module”: {
“abilities”: [
{
// …
“skills”: [
{
“entities”: [
// …
“entity.system.default”
],
“actions”: [
// …
“ohos.want.action.editData”
]
}
]
}
]
}
}


2、启动方



let wantInfo = {
deviceId: ‘’, // deviceId为空表示本设备
// uncomment line below if wish to implicitly query only in the specific bundle.
// bundleName: ‘com.example.myapplication’,
action: ‘ohos.want.action.editData’,
// entities can be omitted.
entities: [‘entity.system.default’],
}

// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(wantInfo).then((data) => {
// …
}).catch((err) => {
// …
})



const RESULT_CODE: number = 1001;
let abilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: ‘com.example.myapplication’,
abilityName: ‘EntryAbility’,
moduleName: ‘entry’,
parameters: {
payResult: ‘OKay’,
},
},
}
// context为被调用方UIAbility的AbilityContext,返回参数
this.context.terminateSelfWithResult(abilityResult, (err) => {
// …
});


3、接收参数



const RESULT_CODE: number = 1001;

let want = {
// Want参数信息
};

// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被调用方UIAbility返回的信息
let payResult = data.want?.parameters?.payResult;
// …
}
}).catch((err) => {
// …
})


#### 🦋6.5 启动UIAbility的指定页面


##### ☀️6.5.1 调用方UIAbility指定启动页面



let wantInfo = {
deviceId: ‘’, // deviceId为空表示本设备
bundleName: ‘com.example.myapplication’,
abilityName: ‘FuncAbility’,
moduleName: ‘module1’, // moduleName非必选
parameters: { // 自定义参数传递页面信息
router: ‘funcA’,
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// …
}).catch((err) => {
// …
})


##### ☀️6.5.2 目标UIAbility首次启动



01;

let want = {
  // Want参数信息
};

// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
    if (data?.resultCode === RESULT_CODE) {
        // 解析被调用方UIAbility返回的信息
        let payResult = data.want?.parameters?.payResult;
        // ...
    }
}).catch((err) => {
    // ...
})

🦋6.5 启动UIAbility的指定页面
☀️6.5.1 调用方UIAbility指定启动页面
let wantInfo = {
    deviceId: '', // deviceId为空表示本设备
    bundleName: 'com.example.myapplication',
    abilityName: 'FuncAbility',
    moduleName: 'module1', // moduleName非必选
    parameters: { // 自定义参数传递页面信息
        router: 'funcA',
    },
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
    // ...
}).catch((err) => {
    // ...
})

☀️6.5.2 目标UIAbility首次启动
  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值