HarmonyOS Developer Stage 模型开发指导

丶龙八夷
发布于 2023-3-22 21:14
浏览
0收藏

进程间通讯

进程模型

HarmonyOS的进程模型:

  • 应用中(同一包名)的所有UIAbility、ServiceExtensionAbility运行在同一个独立进程中。
  • WebView拥有独立的渲染进程。

基于HarmonyOS的进程模型,系统中应用间和应用内都会存在多个进程的情况,因此系统提供了如下两种进程间通信机制:

公共事件

公共事件简介

HarmonyOS通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。

公共事件从系统角度可分为:系统公共事件和自定义公共事件。

  • 系统公共事件:CES内部定义的公共事件,只有系统应用和系统服务才能发布,例如HAP安装,更新,卸载等公共事件。目前支持的系统公共事件详见​​系统公共事件列表​​。
  • 自定义公共事件:应用自定义一些公共事件用来实现跨进程的事件通信能力。

公共事件按发送方式可分为:无序公共事件、有序公共事件和粘性公共事件。

  • 无序公共事件:CES转发公共事件时,不考虑订阅者是否接收到,按订阅者订阅先后顺序转发。
  • 有序公共事件:CES转发公共事件时,按订阅者订阅先后顺序,在接收到前一个订阅者回复后,再转发下一个订阅者。
  • 粘性公共事件:能够让订阅者收到在订阅前已经发送的公共事件就是粘性公共事件。普通的公共事件只能在订阅后发送才能收到,而粘性公共事件的特殊性就是可以先发送后订阅。发送粘性事件必须是系统应用或系统服务,且需要申请ohos.permission.COMMONEVENT_STICKY权限,配置方式请参阅​​访问控制授权申请指导​​。

每个应用都可以按需订阅公共事件,订阅成功,当公共事件发布时,系统会将其发送给对应的应用。这些公共事件可能来自系统、其他应用和应用自身。

图1 公共事件示意图

HarmonyOS Developer Stage 模型开发指导-鸿蒙开发者社区

公共事件订阅

场景介绍

当需要订阅某个公共事件,获取该公共事件传递的参数时,需要创建一个订阅者对象,用于作为订阅公共事件的载体,订阅公共事件并获取公共事件传递而来的参数。订阅部分系统公共事件需要先​​申请权限​​​,订阅这些事件所需要的权限请见​​公共事件权限列表​​。

接口说明

详细接口见​​接口文档​​。

接口名

接口描述

createSubscriber(subscribeInfo: ​​CommonEventSubscribeInfo​​​, callback: AsyncCallback<​​CommonEventData​​>): void

创建订阅者对象(callback)

createSubscriber(subscribeInfo: CommonEventSubscribeInfo): Promise<CommonEventSubscriber>

创建订阅者对象(promise)

subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback): void

订阅公共事件

开发步骤
  1. 导入CommonEvent模块。

import commonEvent from '@ohos.commonEventManager';
  1. 创建订阅者信息,详细的订阅者信息数据类型及包含的参数请见​​CommonEventSubscribeInfo​​​文档介绍。

// 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
let subscriber = null;
// 订阅者信息
let subscribeInfo = {
    events: ["usual.event.SCREEN_OFF"], // 订阅灭屏公共事件
}
  1. 创建订阅者,保存返回的订阅者对象subscriber,用于执行后续的订阅、退订等操作。

// 创建订阅者回调
commonEvent.createSubscriber(subscribeInfo, (err, data) => {
    if (err) {
        console.error(`[CommonEvent] CreateSubscriberCallBack err=${JSON.stringify(err)}`);
    } else {
        console.info(`[CommonEvent] CreateSubscriber success`);
        subscriber = data;
        // 订阅公共事件回调
    }
})
  1. 创建订阅回调函数,订阅回调函数会在接收到事件时触发。订阅回调函数返回的data内包含了公共事件的名称、发布者携带的数据等信息,公共事件数据的详细参数和数据类型请见​​​CommonEventData​​​文档介绍。

// 订阅公共事件回调
if (subscriber !== null) {
    commonEvent.subscribe(subscriber, (err, data) => {
        if (err) {
            console.error(`[CommonEvent] SubscribeCallBack err=${JSON.stringify(err)}`);
        } else {
            console.info(`[CommonEvent] SubscribeCallBack data=${JSON.stringify(data)}`);
        }
    })
} else {
    console.error(`[CommonEvent] Need create subscriber`);
}

公共事件发布

场景介绍

当需要发布某个自定义公共事件时,可以通过publish()方法发布事件。发布的公共事件可以携带数据,供订阅者解析并进行下一步处理。

注意

已发出的粘性公共事件后来订阅者也可以接收到,其他公共事件都需要先订阅再接收,订阅参考​​公共事件订阅章节​​。

接口说明

详细接口见​​接口文档​​。

接口名

接口描述

publish(event: string, callback: AsyncCallback)

发布公共事件。

publish(event: string, options: ​​CommonEventPublishData​​, callback: AsyncCallback)

指定发布信息并发布公共事件。

发布不携带信息的公共事件

不携带信息的公共事件,只能发布无序公共事件。

  1. 导入CommonEvent模块。

import commonEvent from '@ohos.commonEventManager';
  1. 传入需要发布的事件名称和回调函数,发布事件。

// 发布公共事件
commonEvent.publish("usual.event.SCREEN_OFF", (err) => {
    if (err) {
        console.error(`[CommonEvent] PublishCallBack err=${JSON.stringify(err)}`);
    } else {
        console.info(`[CommonEvent] Publish success`);
    }
})
发布携带信息的公共事件

携带信息的公共事件,可以发布为无序公共事件、有序公共事件和粘性事件,可以通过参数​​CommonEventPublishData​​的isOrdered、isSticky的字段进行设置。

  1. 导入CommonEvent模块。

import commonEvent from '@ohos.commonEventManager';
  1. 传入需要发布的事件名称和回调函数,发布事件。

// 公共事件相关信息
let options = {
    code: 1, // 公共事件的初始代码
    data: "initial data", // 公共事件的初始数据
}
  1. 传入需要发布的事件名称、需要发布的指定信息和回调函数,发布事件。

// 发布公共事件
commonEvent.publish("usual.event.SCREEN_OFF", options, (err) => {
    if (err) {
        console.error('[CommonEvent] PublishCallBack err=' + JSON.stringify(err));
    } else {
        console.info('[CommonEvent] Publish success')
    }
})

公共事件取消订阅

场景介绍

订阅者完成业务需要时,需要主动取消订阅,订阅者通过下面方法取消订阅事件。

接口说明

接口名

接口描述

unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback)

取消订阅公共事件

开发步骤
  1. 导入CommonEvent模块。

import commonEvent from '@ohos.commonEventManager';
  1. 根据​​事件订阅章节​​的步骤来订阅某个事件。
  2. 调用CommonEvent中的unsubscribe方法取消订阅某事件。

// subscriber为订阅事件时创建的订阅者对象
if (subscriber !== null) {
    commonEvent.unsubscribe(subscriber, (err) => {
        if (err) {
            console.error(`[CommonEvent] UnsubscribeCallBack err=${JSON.stringify(err)}`)
        } else {
            console.info(`[CommonEvent] Unsubscribe`)
            subscriber = null
        }
    })
}

后台服务

Stage模型提供了ServiceExtensionAbility来提供后台服务的能力,支持系统应用实现一个后台服务并对外提供相应的能力;系统应用A实现了一个后台服务,三方应用B可以通过连接系统应用A的后台服务与其进行进程间通信。

ServiceExtensionAbility的详细介绍请参见​​后台服务开发指导​​。

线程间通讯

线程模型

HarmonyOS应用中每个进程都会有一个主线程,主线程有如下职责:

  1. 负责管理其他线程
  2. 同应用多个UIAbility组件共用一个主线程
  3. 输入事件分发
  4. UI绘制
  5. 应用代码回调(事件处理,生命周期)
  6. 接收Worker发送的消息

除主线程外,还有一类与主线程并行的独立线程Worker,主要用于执行耗时操作,但不可以直接操作UI。Worker线程在主线程中创建,与主线程相互独立。最多可以创建7个Worker:

HarmonyOS Developer Stage 模型开发指导-鸿蒙开发者社区

基于HarmonyOS的线程模型,不同的业务功能运行在不同的线程上,业务功能的交互就需要线程间通信。线程间通信目前主要有Emitter和Worker两种方式,其中Emitter主要适用于线程间的事件同步, Worker主要用于新开一个线程执行耗时任务。

说明:

  • Stage模型只提供了主线程和Worker线程,Emitter主要用于主线程内或者主线程和Worker线程的事件同步。

使用Emitter进行线程间通信

​Emitter​​主要提供线程间发送和处理事件的能力,包括对持续订阅事件或单次订阅事件的处理、取消订阅事件、发送事件到事件队列等。

Emitter的开发步骤如下:

  1. 订阅事件

import emitter from "@ohos.events.emitter";

// 定义一个eventId为1的事件
let event = {
    eventId: 1
};

// 收到eventId为1的事件后执行该回调
let callback = (eventData) => {
    console.info('event callback');
};

// 订阅eventId为1的事件
emitter.on(event, callback);
  1. 发送事件

import emitter from "@ohos.events.emitter";

// 定义一个eventId为1的事件,事件优先级为Low
let event = {
    eventId: 1,
    priority: emitter.EventPriority.LOW
};

let eventData = {
    data: {
        "content": "c",
        "id": 1,
        "isEmpty": false,
    }
};

// 发送eventId为1的事件,事件内容为eventData
emitter.emit(event, eventData);

使用Worker进行线程间通信

​Worker​​是与主线程并行的独立线程。创建Worker的线程被称为宿主线程,Worker工作的线程被称为Worker线程。创建Worker时传入的脚本文件在Worker线程中执行,通常在Worker线程中处理耗时的操作,需要注意的是,Worker中不能直接更新Page。

Worker的开发步骤如下:

  1. 在工程的​​模块级build-profile.json5​​文件的buildOption属性中添加配置信息。

 "buildOption": {
    "sourceOption": {
      "workers": [
        "./src/main/ets/workers/worker.ts"
      ]
    }
  }
  1. 根据build-profile.json5中的配置创建对应的worker.js文件。

import worker from '@ohos.worker';

let parent = worker.workerPort;

// 处理来自主线程的消息
parent.onmessage = function(message) {
    console.info("onmessage: " + message)
    // 发送消息到主线程
    parent.postMessage("message from worker thread.")
}
  1. 主线程中使用如下方式初始化和使用worker。
  • Stage模型:

import worker from '@ohos.worker';

let wk = new worker.ThreadWorker("entry/ets/workers/worker.ts");

// 发送消息到worker线程
wk.postMessage("message from main thread.")

// 处理来自worker线程的消息
wk.onmessage = function(message) {
    console.info("message from worker: " + message)

    // 根据业务按需停止worker线程
    wk.terminate()
}
  • FA模型:

import worker from '@ohos.worker';

let wk = new worker.ThreadWorker("../workers/worker.js");

// 发送消息到worker线程
wk.postMessage("message from main thread.")

// 处理来自worker线程的消息
wk.onmessage = function(message) {
    console.info("message from worker: " + message)

    // 根据业务按需停止worker线程
    wk.terminate()
}

说明:

  • build-profile.json5中配置的worker.ts的相对路径都为./src/main/ets/workers/worker.ts时,在Stage模型下创建worker需要传入路径entry/ets/workers/worker.ts;在FA模型下创建worker需要传入路径../workers/worker.js。
  • 主线程与Worker线程间支持的数据类型参考​​序列化支持类型​​。

Stage模型应用配置文件

应用配置文件中包含应用配置信息、应用组件信息、权限信息、开发者自定义信息等,这些信息在编译构建、分发和运行阶段分别提供给编译工具、应用市场和操作系统使用。

在基于Stage模型开发的应用项目代码下,都存在app.json5(一个)及module.json5(一个或多个)两种配置文件,常用配置项请参见​​应用/组件级配置​​​。对于这两种配置文件的更多介绍,请参见​​应用配置文件(Stage模型)​​。




文章转载自:​​https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/process-model-stage-0000001428061488-V3?catalogVersion=V3​


标签
收藏
回复
举报
回复
    相关推荐