HarmonyOS鸿蒙Next之线程02——EventHandler处理线程间通信

HarmonyOS鸿蒙Next之线程02——EventHandler处理线程间通信 创建一个名为EventHandlerCar设备类型的任务,用于演示EventHandler处理线程间通信的使用。

事件循环器

大家如果有开发Netty或者Node.js应用的话,那么对于事件循环器就不大陌生了,事件循环器是高并发非阻塞的“秘笈”。在HarmonyOS中,事件循环器实现方式就是EventHandler机制。当前线程中处理较为耗时的操作时,如果不希望当前的线程受到阻塞。此时,就可以使用EventHandler机制。EventHandler是HarmonyOS用于处理线程间通信的一种机制,可以通过EventRunner创建新线程,将耗时的操作放到新线程上执行。这样既不阻塞原来的线程,任务又可以得到合理的处理。比如:主线程使用EventHandler创建子线程,子线程做耗时的下载图片操作,下载完成后,子线程通过EventHandler通知主线程,主线程再更新UI。

Netty或者Node.js方面的内容,可以参见本文最后引用部分。

修改ability_main.xml

修改ability_main.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:orientation="vertical">

    <Text
        ohos:id="$+id:text_send_event"
        ohos:height="match_parent"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_main"
        ohos:layout_alignment="horizontal_center"
        ohos:text="Send Event"
        ohos:text_size="50" />
</DirectionalLayout>

显示界面效果如下图1所示

自定义事件处理器

MyEventHandler是自定义的一个事件处理。该事件处理器逻辑比较简单,只是模拟了一个耗时的操作。

package com.waylau.hmos.eventhandler;

import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.concurrent.TimeUnit;

public class MyEventHandler extends EventHandler {
    private static final String TAG = MyEventHandler.class.getSimpleName();
    private static final HiLogLabel LABEL_LOG =
        new HiLogLabel(HiLog.LOG_APP, 0x00001, TAG);

    public MyEventHandler(EventRunner runner) throws IllegalArgumentException {
        super(runner);
    }

    @Override
    public void processEvent(InnerEvent event) {
        super.processEvent(event);
        if (event == null) {
            HiLog.info(LABEL_LOG, "before processEvent event is null");
            return;
        }
        int eventId = event.eventId;
        HiLog.info(LABEL_LOG, "before processEvent eventId: %{public}s", eventId);

        int task1Result = getRandomInt();
        try {
            // 模拟一个耗时的操作
            TimeUnit.MILLISECONDS.sleep(task1Result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        HiLog.info(LABEL_LOG, "after processEvent eventId %{public}s", eventId);
    }

    // 返回随机整数
    private int getRandomInt() {
        // 获取[0, 1000)之间的int整数。方法如下:
        double a = Math.random();
        int result = (int) (a * 1000);
        return result;
    }
}

这个耗时操作,是通过获取一个随机数,而后根据随机数执行线程sleep实现的。

执行事件发送

修改MainAbilitySlice,增加事件发送相关的逻辑。

package com.waylau.hmos.eventhandler.slice;

import com.waylau.hmos.eventhandler.MyEventHandler;
import com.waylau.hmos.eventhandler.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Text;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

public class MainAbilitySlice extends AbilitySlice {
    private static final String TAG = MainAbilitySlice.class.getSimpleName();
    private static final HiLogLabel LABEL_LOG =
        new HiLogLabel(HiLog.LOG_APP, 0x00001, TAG);

    private EventRunner eventRunner = EventRunner.create("MyEventRunner"); // 内部会新建一个线程
    private int eventId = 0; // 事件ID,递增的序列

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        Text textSendEvent =
            (Text) findComponentById(ResourceTable.Id_text_send_event);
        textSendEvent.setClickedListener(listener -> sendEvent());
    }

    private void sendEvent() {
        HiLog.info(LABEL_LOG, "before sendEvent");

        MyEventHandler handler = new MyEventHandler(eventRunner);

        eventId++;
        handler.sendEvent(eventId);

        HiLog.info(LABEL_LOG, "end sendEvent eventId: %{public}s", eventId);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

上述代码,

  • Text增加了点击事件,以触发sendEvent任务
  • sendEvent方法中创建了EventHandler事件处理器
  • 通过EventHandlersendEvent方法发送了一个事件ID。事件ID是自增的序列。

运行

运行应用后,点击3次界面文本“Start Event”以触发事件派发。此时,控制台输出如下:

01-15 14:47:05.056 3943-3943/com.waylau.hmos.eventhandler I 00001/MainAbilitySlice: before sendEvent
01-15 14:47:05.057 3943-3943/com.waylau.hmos.eventhandler I 00001/MainAbilitySlice: end sendEvent eventId: 1
01-15 14:47:05.058 3943-4024/com.waylau.hmos.eventhandler I 00001/MyEventHandler: before processEvent eventId: 1
01-15 14:47:05.196 3943-4024/com.waylau.hmos.eventhandler I 00001/MyEventHandler: after processEvent eventId 1

01-15 14:47:07.731 3943-3943/com.waylau.hmos.eventhandler I 00001/MainAbilitySlice: before sendEvent
01-15 14:47:07.732 3943-4024/com.waylau.hmos.eventhandler I 00001/MyEventHandler: before processEvent eventId: 2
01-15 14:47:07.732 3943-3943/com.waylau.hmos.eventhandler I 00001/MainAbilitySlice: end sendEvent eventId: 2
01-15 14:47:08.104 3943-4024/com.waylau.hmos.eventhandler I 00001/MyEventHandler: after processEvent eventId 2

01-15 14:47:09.149 3943-3943/com.waylau.hmos.eventhandler I 00001/MainAbilitySlice: before sendEvent
01-15 14:47:09.151 3943-3943/com.waylau.hmos.eventhandler I 00001/MainAbilitySlice: end sendEvent eventId: 3
01-15 14:47:09.159 3943-4024/com.waylau.hmos.eventhandler I 00001/MyEventHandler: before processEvent eventId: 3
01-15 14:47:09.300 3943-4024/com.waylau.hmos.eventhandler I 00001/MyEventHandler: after processEvent eventId 3

分别执行了3次可以看到MainAbilitySlice先是发送了事件,而后MyEventHandler就处理了事件。

参考引用

11 回复

子线程通过EventHandler通知主线程,主线程再更新UI。这个内容呢?只是发了事件,处理完成后的数据更新到UI线程呢,不能搞个完整的例子吗?

更多关于HarmonyOS鸿蒙Next之线程02——EventHandler处理线程间通信的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


似乎挺难的,无奈了

一直觉得这内容有内涵

一起顶,让更多的人看到

这才是我需要的,谢谢你的分享

如何吃透,交个方法

楼主真是见多识广啊,懂的好多

膜拜呀,请接受我的膝盖

在HarmonyOS中,EventHandler是用于处理线程间通信的核心机制之一。它允许开发者在不同线程之间传递消息并执行相应的任务。EventHandler基于事件驱动模型,通过消息队列实现线程间的异步通信。

EventHandler的主要功能包括:

  1. 消息发送:通过sendEventpostEvent方法将消息发送到目标线程的消息队列中。
  2. 消息处理:在目标线程中,EventHandler会从消息队列中取出消息,并调用相应的回调函数进行处理。
  3. 线程切换EventHandler可以确保消息在指定的线程中执行,从而实现线程切换。

使用EventHandler时,开发者需要创建一个继承自EventHandler的类,并重写processEvent方法以处理接收到的消息。通过EventRunner创建并启动一个事件循环,EventHandler会绑定到该事件循环上,从而在指定的线程中处理消息。

示例代码:

import { EventHandler, EventRunner, Event } from '@ohos.eventhandler';

class MyEventHandler extends EventHandler {
  processEvent(event: Event): void {
    // 处理接收到的消息
    console.log("Received event:", event.eventId);
  }
}

// 创建事件循环
let runner = new EventRunner();
let handler = new MyEventHandler(runner);

// 发送消息
let event = new Event(1); // 1为事件ID
handler.sendEvent(event);

EventHandler适用于需要在不同线程间传递消息并执行任务的场景,如UI线程与后台线程的通信。通过EventHandler,开发者可以简化线程间通信的复杂性,提高代码的可维护性和可读性。

在HarmonyOS鸿蒙Next中,EventHandler是用于处理线程间通信的核心组件。它允许开发者在不同线程之间传递消息和执行任务,确保UI线程的流畅性。通过EventHandler,开发者可以将耗时操作放在后台线程执行,完成后通过消息机制通知UI线程更新界面。EventHandler提供了sendMessagepostTask等方法,支持异步消息传递和任务调度,有效避免了线程阻塞和资源竞争问题,提升了应用的响应速度和稳定性。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!