场景介绍
EventHandler开发场景
EventHandler的主要功能是将InnerEvent事件或者Runnable任务投递到其他的线程进行处理,其使用的场景包括:
- InnerEvent事件:开发者需要将InnerEvent事件投递到新的线程,按照优先级和延时进行处理。投递时,EventHandler的优先级可在IMMEDIATE、HIGH、LOW、IDLE中选择,并设置合适的delayTime。
- Runnable任务:开发者需要将Runnable任务投递到新的线程,并按照优先级和延时进行处理。投递时,EventHandler的优先级可在IMMEDIATE、HIGH、LOW、IDLE中选择,并设置合适的delayTime。
- 开发者需要在新创建的线程里投递事件到原线程进行处理。
EventRunner工作模式
EventRunner的工作模式可以分为托管模式和手动模式。两种模式是在调用EventRunner的create()方法时,通过选择不同的参数来实现的,详见API参考。默认为托管模式。
- 托管模式:不需要开发者调用run()和stop()方法去启动和停止EventRunner。当EventRunner实例化时,系统调用run()来启动EventRunner;当EventRunner不被引用时,系统调用stop()来停止EventRunner。
- 手动模式:需要开发者自行调用EventRunner的run()方法和stop()方法来确保线程的启动和停止。
接口说明
EventHandler
- EventHandler的属性Priority(优先级)介绍:EventRunner将根据优先级的高低从事件队列中获取事件或者Runnable任务进行处理。
开发步骤
EventHandler投递InnerEvent事件
EventHandler投递InnerEvent事件,并按照优先级和延时进行处理,开发步骤如下:
- 创建EventHandler的子类,在子类中重写实现方法processEvent()来处理事件。
private static final int EVENT_MESSAGE_NORMAL = 1;
private static final int EVENT_MESSAGE_DELAY = 2;
private class MyEventHandler extends EventHandler {
private MyEventHandler(EventRunner runner) {
super(runner);
}
// 重写实现processEvent方法
@Override
public void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) {
return;
}
int eventId = event.eventId;
switch (eventId) {
case EVENT_MESSAGE_NORMAL:
// 待执行的操作,由开发者定义
break;
case EVENT_MESSAGE_DELAY:
// 待执行的操作,由开发者定义
break;
default:
break;
}
}
}
创建EventRunner,以手动模式为例。
EventRunner runner = EventRunner.create(false);// create()的参数是true时,则为托管模式
创建EventHandler子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
获取InnerEvent事件。
// 获取事件实例,其属性eventId, param, object由开发者确定,代码中只是示例。
long param = 0L;
Object object = null;
InnerEvent normalInnerEvent = InnerEvent.get(EVENT_MESSAGE_NORMAL, param, object);
InnerEvent delayInnerEvent = InnerEvent.get(EVENT_MESSAGE_DELAY, param, object);
投递事件,投递的优先级以IMMEDIATE为例,延时选择0ms和2ms。
// 优先级IMMEDIATE,投递之后立即处理,延时为0ms,该语句等价于同步投递sendSyncEvent(event1,EventHandler.Priority.IMMEDIATE);
myHandler.sendEvent(normalInnerEvent, 0, EventHandler.Priority.IMMEDIATE);
myHandler.sendEvent(delayInnerEvent, 2, EventHandler.Priority.IMMEDIATE); // 延时2ms后立即处理
启动和停止EventRunner,如果为托管模式,则不需要此步骤。
runner.run();
// 待执行操作
runner.stop();// 开发者根据业务需要在适当时机停止EventRunner
EventHandler投递Runnable任务
EventHandler投递Runnable任务,并按照优先级和延时进行处理,开发步骤如下:
- 创建EventHandler的子类,创建EventRunner,并创建EventHandler子类的实例,步骤与EventHandler投递InnerEvent场景的步骤1-3相同。
- 创建Runnable任务。
Runnable normalTask = new Runnable() {
@Override
public void run() {
// 待执行的操作,由开发者定义
}
};
Runnable delayTask = new Runnable() {
@Override
public void run() {
// 待执行的操作,由开发者定义
}
};
投递Runnable任务,投递的优先级以IMMEDIATE为例,延时选择0ms和2ms。
// 优先级为immediate,延时0ms,该语句等价于同步投递myHandler.postSyncTask(task1,EventHandler.Priority.IMMEDIATE);
myHandler.postTask(normalTask, 0, EventHandler.Priority.IMMEDIATE);
myHandler.postTask(delayTask, 2, EventHandler.Priority.IMMEDIATE);// 延时2ms后立即执行
启动和停止EventRunner,如果是托管模式,则不需要此步骤。
runner.run();
// 待执行操作
runner.stop();// 停止EventRunner
在新创建的线程里投递事件到原线程
EventHandler从新创建的线程投递事件到原线程并进行处理,开发步骤如下:
- 创建EventHandler的子类,在子类中重写实现方法processEvent()来处理事件。
private static final int EVENT_MESSAGE_CROSS_THREAD = 1;
private class MyEventHandler extends EventHandler {
private MyEventHandler(EventRunner runner) {
super(runner);
}
// 重写实现processEvent方法
@Override
public void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) {
return;
}
int eventId = event.eventId;
switch (eventId) {
case EVENT_MESSAGE_CROSS_THREAD:
Object object = event.object;
if (object instanceof EventRunner) {
// 将原先线程的EventRunner实例投递给新创建的线程
EventRunner runner2 = (EventRunner) object;
// 将原先线程的EventRunner实例与新创建的线程的EventHandler绑定
EventHandler myHandler2 = new EventHandler(runner2) {
@Override
public void processEvent(InnerEvent event) {
// 需要在原先线程执行的操作
}
};
int eventId2 = 1;
long param2 = 0L;
Object object2 = null;
InnerEvent event2 = InnerEvent.get(eventId2, param2, object2);
myHandler2.sendEvent(event2); // 投递事件到原先的线程
}
break;
default:
break;
}
}
}
创建EventRunner,以手动模式为例。
EventRunner runner = EventRunner.create(false);// create()的参数是true时,则为托管模式。
创建EventHandler子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
获取InnerEvent事件。
// 获取事件实例,其属性eventId, param, object由开发者确定,代码中只是示例。
long param = 0L;
InnerEvent event = InnerEvent.get(EVENT_MESSAGE_CROSS_THREAD, param, EventRunner.current());
投递事件,在新线程上直接处理。
// 将与当前线程绑定的EventRunner投递到与runner创建的新线程中
myHandler.sendEvent(event);
启动和停止EventRunner,如果是托管模式,则不需要此步骤。
runner.run();
// 待执行操作
runner.stop();// 停止EventRunner
完整代码示例
非托管情况:
// 全局:
public static final int CODE_DOWNLOAD_FILE1 = 1;
public static final int CODE_DOWNLOAD_FILE2 = 2;
public static final int CODE_DOWNLOAD_FILE3 = 3;
// 线程A:
EventRunner runnerA = EventRunner.create(false);
runnerA.run(); // run之后一直循环卡在这里,所以需要新建一个线程run
// 线程B:
// 1.创建类继承EventHandler
public class MyEventHandler extends EventHandler {
private MyEventHandler(EventRunner runner) {
super(runner);
}
@Override
public void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) {
return;
}
int eventId = event.eventId;
switch (eventId) {
case CODE_DOWNLOAD_FILE1: {
// 待执行的操作,由开发者定义
break;
}
case CODE_DOWNLOAD_FILE2: {
// 待执行的操作,由开发者定义
break;
}
case CODE_DOWNLOAD_FILE3: {
// 待执行的操作,由开发者定义
break;
}
default:
break;
}
}
}
// 2.创建MyEventHandler实例
MyEventHandler handler = new MyEventHandler(runnerA);
// 3.向线程A发送事件
handler.sendEvent(CODE_DOWNLOAD_FILE1);
handler.sendEvent(CODE_DOWNLOAD_FILE2);
handler.sendEvent(CODE_DOWNLOAD_FILE3);
// 4.runnerA不再使用后,退出
runnerA.stop();
托管情况:
// 全局:
public static final int CODE_DOWNLOAD_FILE1 = 1;
public static final int CODE_DOWNLOAD_FILE2 = 2;
public static final int CODE_DOWNLOAD_FILE3 = 3;
// 1.创建EventRunner A:
EventRunner runnerA = EventRunner.create("downloadRunner"); // 内部会新建一个线程
// 2.创建类继承EventHandler
public class MyEventHandler extends EventHandler {
private MyEventHandler(EventRunner runner) {
super(runner);
}
@Override
public void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) {
return;
}
int eventId = event.eventId;
switch (eventId) {
case CODE_DOWNLOAD_FILE1: {
// 待执行的操作,由开发者定义
break;
}
case CODE_DOWNLOAD_FILE2: {
// 待执行的操作,由开发者定义
break;
}
case CODE_DOWNLOAD_FILE3: {
// 待执行的操作,由开发者定义
break;
}
default:
break;
}
}
}
// 3.创建MyEventHandler实例
MyEventHandler handler = new MyEventHandler(runnerA);
// 4.向线程A发送事件
handler.sendEvent(CODE_DOWNLOAD_FILE1);
handler.sendEvent(CODE_DOWNLOAD_FILE2);
handler.sendEvent(CODE_DOWNLOAD_FILE3);
// 5.runnerA没有任何对象引入时,线程会自动回收
runnerA = null;
相关实例
针对线程间通信,有以下示例工程可供参考:
- EventHandler本示例演示了将InnerEvent事件投递到新的线程、将Runnable任务投递到新的线程、在新创建的线程里投递事件到原线程进行处理三种场景。
针对线程间通信,有以下Codelabs可供参考:
- 分布式鉴权(Java)介绍如何使用HarmonyOS实现一个带有儿童模式的简单小游戏。
- 分布式运动健康应用(智能穿戴端)基于分布式数据服务和传感器模块,实现智能穿戴和手机间数据同步以及心率等健康数据的获取。
- 分布式游戏手柄基于分布式能力,将手机作为智慧屏的虚拟手柄终端,组成全新的多人娱乐场景。
- AI语音播报系统基于AI语音播报能力,朗读输入的文字内容。