百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

线程通信EventHandler使用

haoteby 2025-08-02 18:13 13 浏览


作者:韩茹

公司:程序咖(北京)科技有限公司

鸿蒙巴士专栏作家

一、使用场景

EventHandler开发场景

EventHandler的主要功能是将InnerEvent事件或者Runnable任务投递到其他的线程进行处理,其使用的场景包括:

  • 开发者需要将InnerEvent事件投递到新的线程,按照优先级和延时进行处理。投递时,EventHandler的优先级可在IMMEDIATE、HIGH、LOW、IDLE中选择,并设置合适的delayTime。
  • 开发者需要将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,允许在异步线程上发送和处理InnerEvent和Runnable对象。每个EventHandler实例都绑定一个线程,该线程有一个事件队列。线程周期性地从事件队列中检索事件,并将事件分派给EventHandler进行处理。EventHandler将事件或Runnable任务传递到线程的事件队列,并在事件或任务从事件队列中出来时执行它。

您可以使用EventHandler在不同的线程之间调度和处理事件和Runnable 对象,并将事件或Runnable 对象安排在特定的时间间隔内进行处理。

您可以使用此类中提供的方法发送同步或异步事件、延迟事件处理以及设置事件优先级。

您需要重写processEvent(
ohos.eventhandler.InnerEvent)方法来处理事件。

EventHandler类的定义:

java.lang.Object

|---ohos.eventhandler.EventHandler
public class EventHandler extends Object

EventHandler的属性Priority(优先级)介绍:

EventRunner将根据优先级的高低从事件队列中获取事件或者Runnable任务进行处理。

属性

描述

Priority.IMMEDIATE

表示事件被立即投递

Priority.HIGH

表示事件先于LOW优先级投递

Priority.LOW

表示事件优于IDLE优先级投递,事件的默认优先级是LOW

Priority.IDLE

表示在没有其他事件的情况下,才投递该事件

EventHandler的主要方法介绍:

接口名

描述

EventHandler(EventRunner runner)

利用已有的EventRunner来创建EventHandler

current()

在processEvent回调中,获取当前的EventHandler

processEvent(InnerEvent event)

回调处理事件,由开发者实现

sendEvent(InnerEvent event)

发送一个事件到事件队列,延时为0ms, 优先级为LOW

sendEvent(InnerEvent event, long delayTime)

发送一个延时事件到事件队列,优先级为LOW

sendEvent(InnerEvent event, long delayTime, EventHandler.Priority priority)

发送一个指定优先级的延时事件到事件队列

sendEvent(InnerEvent event, EventHandler.Priority priority)

发送一个指定优先级的事件到事件队列,延时为0ms

sendSyncEvent(InnerEvent event)

发送一个同步事件到事件队列,延时为0ms,优先级为LOW

sendSyncEvent(InnerEvent event, EventHandler.Priority priority)

发送一个指定优先级的同步事件到事件队列,延时为0ms,优先级不可以是IDLE

postSyncTask(Runnable task)

发送一个Runnable同步任务到事件队列,延时为0ms, 优先级为LOW

postSyncTask(Runnable task, EventHandler.Priority priority)

发送一个指定优先级的Runnable同步任务到事件队列,延时为0ms

postTask(Runnable task)

发送一个Runnable任务到事件队列,延时为0ms,优先级为LOW

postTask(Runnable task, long delayTime)

发送一个Runnable延时任务到事件队列,优先级为LOW

postTask(Runnable task, long delayTime, EventHandler.Priority priority)

发送一个指定优先级的Runnable延时任务到事件队列

postTask(Runnable task, EventHandler.Priority priority)

发送一个指定优先级的Runnable任务到事件队列,延时为0ms

sendTimingEvent(InnerEvent event, long taskTime)

发送一个定时事件到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行,优先级为LOW

sendTimingEvent(InnerEvent event, long taskTime, EventHandler.Priority priority)

发送一个带优先级的事件到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行

postTimingTask(Runnable task, long taskTime)

发送一个Runnable任务到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行,优先级为LOW

postTimingTask(Runnable task, long taskTime, EventHandler.Priority priority)

发送一个带优先级的Runnable任务到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行

removeEvent(int eventId)

删除指定id的事件

removeEvent(int eventId, long param)

删除指定id和param的事件

removeEvent(int eventId, long param, Object object)

删除指定id、param和object的事件

removeAllEvent()

删除该EventHandler的所有事件

getEventName(InnerEvent event)

获取事件的名字

getEventRunner()

获取该EventHandler绑定的EventRunner

isIdle()

判断队列是否为空

hasInnerEvent(Runnable runnable)

根据指定的runnable参数,检查是否有还未被处理的任务。可以根据不同的入参进行检查,详见EventHandler

三、EventRunner

EventRunner,在当前线程中创建和管理事件队列。

调用run()方法后,EventRunner将从事件队列中连续检索事件,并将事件分派给匹配的EventHandler。然后将调用EventHandler#processEvent(InnerEvent)方法来处理事件。

EventRunner类定义。

java.lang.Object

|---ohos.eventhandler.EventRunner

public final class EventRunner extends Object

EventRunner的主要方法介绍:

接口名

描述

create()

创建一个拥有新线程的EventRunner

create(boolean inNewThread)

创建一个拥有新线程的EventRunner,inNewThread为true时,EventRunner为托管模式,系统将自动管理该EventRunner;inNewThread为false时,EventRunner为手动模式

create(String newThreadName)

创建一个拥有新线程的EventRunner, 新线程的名字是 newThreadName

current()

获取当前线程的EventRunner

run()

EventRunner为手动模式时,调用该方法启动新的线程

stop()

EventRunner为手动模式时,调用该方法停止新的线程

四、InnerEvent

InnerEvent,用于定义可以发送到EventHandler的事件的结构。

InnerEvent类的定义:

public final class InnerEvent
extends Object
implements Sequenceable

一个InnerEvent 对象,包含了一个额外的整数字段和一个额外的对象字段来携带特定数据。

InnerEvent的属性介绍:

属性

描述

eventId

事件的ID, 由开发者定义用来辨别事件

object

事件携带的Object信息

param

事件携带的long型数据

InnerEvent的构造函数是私有的。因此,需要调用get()方法来创建InnerEvent实例。该方法将从回收对象池中提取InnerEvent实例。

常用方法:

方法名

描述

drop()

释放一个事件实例

get()

获得一个事件实例

get(int eventId)

获得一个指定的eventId的事件实例

get(int eventId, long param)

获得一个指定的eventId和param的事件实例

get(int eventId, long param, Object object)

获得一个指定的eventId,param和object的事件实例

get(int eventId, Object object)

获得一个指定的eventId和object的事件实例

PacMap getPacMap()

获取PacMap,如果没有,会新建一个

Runnable getTask()

获取Runnable任务

PacMap peekPacMap()

获取PacMap

void setPacMap(PacMap pacMap)

设置PacMap

更多方法请查看,官方API

五、流程逻辑

5.1 EventHandler投递InnerEvent事件

EventHandler投递InnerEvent事件,并按照优先级和延时进行处理,开发步骤如下:

  1. 创建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;
           }
       }
   }
  1. 创建EventRunner,以手动模式为例。
   EventRunner runner = EventRunner.create(false);// create()的参数是true时,则为托管模式
  1. 创建EventHandler子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
  1. 获取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);
  1. 投递事件,投递的优先级以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后立即处理
  1. 启动和停止EventRunner,如果为托管模式,则不需要此步骤。
   runner.run();// 待执行操作runner.stop();// 开发者根据业务需要在适当时机停止EventRunner

5.2 EventHandler投递Runnable任务

EventHandler投递Runnable任务,并按照优先级和延时进行处理,开发步骤如下:

  1. 创建EventHandler的子类,创建EventRunner,并创建EventHandler子类的实例,步骤与EventHandler投递InnerEvent场景的步骤1-3相同。
  2. 创建Runnable任务。
   Runnable normalTask = new Runnable() {
       @Override
       public void run() {
           // 待执行的操作,由开发者定义
       }
   };
   Runnable delayTask = new Runnable() {
       @Override
       public void run() {
           // 待执行的操作,由开发者定义
       }
   };
  1. 投递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后立即执行
  1. 启动和停止EventRunner,如果是托管模式,则不需要此步骤。
   runner.run();
   // 待执行操作
   
   runner.stop();// 停止EventRunner

5.3 在新创建的线程里投递事件到原线程

EventHandler从新创建的线程投递事件到原线程并进行处理,开发步骤如下:

  1. 创建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;
           }
       }
   }
  1. 创建EventRunner,以手动模式为例。
   EventRunner runner = EventRunner.create(false);// create()的参数是true时,则为托管模式。
  1. 创建EventHandler子类的实例。
   MyEventHandler myHandler = new MyEventHandler(runner);
  1. 获取InnerEvent事件。
// 获取事件实例,其属性eventId, param, object由开发者确定,代码中只是示例。
long param = 0L; 
InnerEvent event = InnerEvent.get(EVENT_MESSAGE_CROSS_THREAD, param, EventRunner.current());
  1. 投递事件,在新线程上直接处理。
// 将与当前线程绑定的EventRunner投递到与runner创建的新线程中
myHandler.sendEvent(event);
  1. 启动和停止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;

七、示例代码

1、EventHandler投递InnerEvent事件

我们现在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:padding="20vp"
    ohos:orientation="vertical">


    <Button
        ohos:id="$+id:btn1"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:text="EventHandler投递InnerEvent事件"
        ohos:background_element="#eeeeee"
        ohos:padding="20vp"
        ohos:multiple_lines="true"
        ohos:text_size="20fp"
        ohos:margin="10vp"
        />


</DirectionalLayout>

然后在MainAbility中处理该按钮的点击事件,投递InnerEvent事件:

package com.example.hanrueventhandler.slice;

import com.example.hanrueventhandler.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

public class MainAbilitySlice extends AbilitySlice {

    private static final int EVENT_MESSAGE_NORMAL = 1;
    private static final int EVENT_MESSAGE_DELAY = 2;
    // 定义日志标签
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");

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

    }

    public void initComponent(){
        findComponentById(ResourceTable.Id_btn1).setClickedListener(component -> eventHandlerPostInnerEvent());
    }


    // 按钮1:EventHandler投递InnerEvent事件
    public void eventHandlerPostInnerEvent(){
        // 2.创建EventRunner,手动模式或者托管模式
        EventRunner runner = EventRunner.create(true);// create()的参数是true时,则为托管模式

        // 3.创建EventHandler子类的实例。
        MyEventHandler myHandler = new MyEventHandler(runner);

        // 4.获取InnerEvent事件。
        // 获取事件实例,其属性eventId, param, object由开发者确定。
        long param1 = 9527L;
        Object object1 = "我是王二狗";
        InnerEvent normalInnerEvent = InnerEvent.get(EVENT_MESSAGE_NORMAL, param1, object1);

        long param2 = 1314L;
        Object object2 = "鸿蒙巴士";
        InnerEvent delayInnerEvent = InnerEvent.get(EVENT_MESSAGE_DELAY, param2, object2);

        HiLog.info(LABEL," 。。。");


        // 5.投递事件,投递的优先级以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后立即处理

        // 6.启动和停止EventRunner,如果为托管模式,则不需要此步骤。
        // runner.run();
        // 待执行操作
        // runner.stop();// 开发者根据业务需要在适当时机停止EventRunner

    }

    // 1.创建EventHandler的子类,在子类中重写实现方法processEvent()来处理事件。
    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;
            long param = event.param;
            Object object = event.object;
            HiLog.info(LABEL,"子线程。。。线程ID"+Thread.currentThread().getId()+",线程名称:"+Thread.currentThread().getName());
            switch (eventId) {
                case EVENT_MESSAGE_NORMAL:
                    // 待执行的操作,由开发者定义
                    HiLog.info(LABEL," 子线程中要处理的操作1。。。"+param+","+ object.toString());

                    break;
                case EVENT_MESSAGE_DELAY:
                    // 待执行的操作,由开发者定义
                    HiLog.info(LABEL," 子线程中要处理的操作2。。。"+param+","+ object.toString());
                    break;
                default:
                    break;
            }
        }
    }

}

运行程序,并点击按钮1:

2、EventHandler投递Runnable任务

我们现在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:padding="20vp"
    ohos:orientation="vertical">

		...
    <Button
        ohos:id="$+id:btn2"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:text="EventHandler投递Runnable任务"
        ohos:background_element="#eeeeee"
        ohos:multiple_lines="true"
        ohos:padding="20vp"
        ohos:text_size="20fp"
        ohos:margin="10vp"
        />


</DirectionalLayout>

然后在MainAbility中处理该按钮的点击事件,投递Runnable任务:


    public void initComponent(){
        findComponentById(ResourceTable.Id_btn1).setClickedListener(component -> eventHandlerPostInnerEvent());
        findComponentById(ResourceTable.Id_btn2).setClickedListener(component -> eventHandlerPostRunnableTask());
    }

    // 2.EventHandler投递Runnable任务
    public void eventHandlerPostRunnableTask(){
        // 2.创建EventRunner,手动模式或者托管模式
        EventRunner runner = EventRunner.create(true);// create()的参数是true时,则为托管模式

        // 3.创建EventHandler子类的实例。
        MyEventHandler myHandler = new MyEventHandler(runner);

        // 4.创建Runnable任务。
        Runnable normalTask = new Runnable() {
            @Override
            public void run() {
                // 待执行的操作,由开发者定义
                HiLog.info(LABEL,"子线程ID:"+Thread.currentThread().getId()+",子线程名称:"+Thread.currentThread().getName()+"--->Runnable的normalTask");
            }
        };
        Runnable delayTask = new Runnable() {
            @Override
            public void run() {
                // 待执行的操作,由开发者定义
                HiLog.info(LABEL,"子线程ID:"+Thread.currentThread().getId()+",子线程名称:"+Thread.currentThread().getName()+"--->Runnable的delayTask");
            }
        };
        HiLog.info(LABEL," 。。。。。。");
        // 5.投递
        // 优先级为immediate,延时0ms,该语句等价于同步投递myHandler.postSyncTask(task1,EventHandler.Priority.immediate);
        myHandler.postTask(normalTask, 0, EventHandler.Priority.IMMEDIATE);

        myHandler.postTask(delayTask, 2, EventHandler.Priority.IMMEDIATE);// 延时2ms后立即执行



        // 6.启动和停止EventRunner,如果为托管模式,则不需要此步骤。
        // runner.run();
        // 待执行操作
        // runner.stop();// 停止EventRunner
    }

    

运行程序,并点击按钮2:

3、在新创建的线程里投递事件到原线程

我们现在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:padding="20vp"
    ohos:orientation="vertical">

		...
    <Button
        ohos:id="$+id:btn3"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:text="在新创建的线程里投递事件到原线程"
        ohos:background_element="#eeeeee"
        ohos:padding="20vp"
        ohos:multiple_lines="true"
        ohos:text_size="20fp"
        ohos:margin="10vp"
        />


</DirectionalLayout>

然后在MainAbility中处理该按钮的点击事件,在新创建的线程里投递事件到原线程:

public void initComponent(){
        findComponentById(ResourceTable.Id_btn1).setClickedListener(component -> eventHandlerPostInnerEvent());
        findComponentById(ResourceTable.Id_btn2).setClickedListener(component -> eventHandlerPostRunnableTask());
        findComponentById(ResourceTable.Id_btn3).setClickedListener(component -> postInnerEventToOriginalThread());
    }

    // 3.在新创建的线程里投递事件到原线程
    public void postInnerEventToOriginalThread(){
        // 2.创建EventRunner,手动模式或者托管模式
        EventRunner runner = EventRunner.create(true);// create()的参数是true时,则为托管模式

        // 3.创建EventHandler子类的实例。
        MyEventHandler myHandler = new MyEventHandler(runner);

        // 4.获取InnerEvent事件。
        // 获取事件实例,其属性eventId, param, object由开发者确定。
        long param = 723L;
        // 注意:这里的第三个参数Object,要传入当前线程对象。
        InnerEvent event = InnerEvent.get(EVENT_MESSAGE_CROSS_THREAD, param, EventRunner.current());

        // 5.投递事件,将与当前线程绑定的EventRunner投递到与runner创建的新线程中
        myHandler.sendEvent(event);


        // 6.启动和停止EventRunner,如果为托管模式,则不需要此步骤。
        // runner.run();
        // 待执行操作
        // runner.stop();// 开发者根据业务需要在适当时机停止EventRunner
    }

然后我们在MyEventHandler中,再加一个case进行处理:

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;
            long param = event.param;
            Object object = event.object;
            HiLog.info(LABEL,"子线程。。。线程ID"+Thread.currentThread().getId()+",线程名称:"+Thread.currentThread().getName());
            switch (eventId) {
                case EVENT_MESSAGE_NORMAL:
                    // 待执行的操作,由开发者定义
                    break;
                case EVENT_MESSAGE_DELAY:
                    // 待执行的操作,由开发者定义
                    break;
                case EVENT_MESSAGE_CROSS_THREAD:
                    if (object instanceof EventRunner) {
                        HiLog.info(LABEL," 子线程中要处理的操作3。。。"+param+","+ object.toString());
                        // 将原先线程的EventRunner实例投递给新创建的线程
                        EventRunner runner2 = (EventRunner) object;
                        // 将原先线程的EventRunner实例与新创建的线程的EventHandler绑定
                        EventHandler myHandler2 = new EventHandler(runner2) {
                            @Override
                            public void processEvent(InnerEvent event) {
                                // 需要在原先线程执行的操作
                                HiLog.info(LABEL," 原先的线程。。。"+Thread.currentThread().getId()+","+Thread.currentThread().getName());
                                HiLog.info(LABEL," 原先的线程。。。eventId"+event.eventId+",param:"+event.param+",object:"+event.object);
                            }
                        };
                        int eventId2 = 1;
                        long param2 = 9988L;
                        Object object2 = "我是小白菜";
                        InnerEvent event2 = InnerEvent.get(eventId2, param2, object2);
                        myHandler2.sendEvent(event2); // 投递事件到原先的线程
                    }
                    break;
                default:
                    break;
            }
        }
    }

运行程序,并点击按钮3:



相关推荐

一日一技:用Python程序将十进制转换为二进制

用Python程序将十进制转换为二进制通过将数字连续除以2并以相反顺序打印其余部分,将十进制数转换为二进制。在下面的程序中,我们将学习使用递归函数将十进制数转换为二进制数,代码如下:...

十进制转化成二进制你会吗?#数学思维

六年级奥赛起跑线:抽屉原理揭秘。同学们好,我是你们的奥耀老师。今天一起来学习奥赛起跑线第三讲二进制计数法。例一:把十进制五十三化成二进制数是多少?首先十进制就是满十进一,二进制就是满二进一。二进制每个...

二进制、十进制、八进制和十六进制,它们之间是如何转换的?

在学习进制时总会遇到多种进制转换的时候,学会它们之间的转换方法也是必须的,这里分享一下几种进制之间转换的方法,也分享两个好用的转换工具,使用它们能够大幅度的提升你的办公和学习效率,感兴趣的小伙伴记得点...

c语言-2进制转10进制_c语言 二进制转十进制

#include<stdio.h>intmain(){charch;inta=0;...

二进制、八进制、十进制和十六进制数制转换

一、数制1、什么是数制数制是计数进位的简称。也就是由低位向高位进位计数的方法。2、常用数制计算机中常用的数制有二进制、八进制、十进制和十六进制。...

二进制、十进制、八进制、十六进制间的相互转换函数

二进制、十进制、八进制、十六进制间的相互转换函数1、输入任意一个十进制的整数,将其分别转换为二进制、八进制、十六进制。2、程序代码如下:#include<iostream>usingna...

二进制、八进制、十进制和十六进制等常用数制及其相互转换

从大学开始系统的接触计算机专业,到现在已经过去十几年了,今天整理一下基础的进制转换,希望给还在上高中的表妹一个入门的引导,早日熟悉这个行业。一、二进制、八进制、十进制和十六进制是如何定义的?二进制是B...

二进制如何转换成十进制?_二进制如何转换成十进制例子图解

随着社会的发展,电器维修由继电器时代逐渐被PLC,变频器,触摸屏等工控时代所替代,特别是plc编程,其数据逻辑往往涉及到数制二进制,那么二进制到底是什么呢?它和十进制又有什么区别和联系呢?下面和朋友们...

二进制与十进制的相互转换_二进制和十进制之间转换

很多同学在刚开始接触计算机语言的时候,都会了解计算机的世界里面大多都是二进制来表达现实世界的任何事物的。当然现实世界的事务有很多很多,就拿最简单的数字,我们经常看到的数字大多都是十进制的形式,例如:我...

十进制如何转换为二进制,二进制如何转换为十进制

用十进制除以2,除的断的,商用0表示;除不断的,商用1表示余0时结束假如十进制用X表示,用十进制除以2,即x/2除以2后为整数的(除的断的),商用0表示;除以2除不断的,商用1表示除完后的商0或1...

十进制数如何转换为二进制数_十进制数如何转换为二进制数举例说明

我们经常听到十进制数和二进制数,电脑中也经常使用二进制数来进行计算,但是很多人却不清楚十进制数和二进制数是怎样进行转换的,下面就来看看,十进制数转换为二进制数的方法。正整数转二进制...

二进制转化为十进制,你会做吗?一起来试试吧

今天孩子问把二进制表示的110101改写成十进制数怎么做呀?,“二进制”简单来说就是“满二进一”,只用0和1共两个数字表示,同理我们平常接触到的“十进制”是“满十进一”,只用0-9共十个数字表示。如果...

Mac终于能正常打游戏了!苹果正逐渐淘汰Rosetta转译

Mac玩家苦转译久矣!WWDC2025苹果正式宣判Rosetta死刑,原生游戏时代终于杀到。Metal4光追和AI插帧技术直接掀桌,连Steam都连夜扛着ARM架构投诚了。看到《赛博朋克2077》...

怎么把视频的声音提出来转为音频?音频提取,11款工具实测搞定

想把视频里的声音单独保存为音频文件(MP3/AAC/WAV/FLAC)用于配音、播客、听课或二次剪辑?本文挑出10款常用工具,给出实测可复现的操作步骤、优缺点和场景推荐。1)转换猫mp3转换器(操作门...

6个mp4格式转换器测评:转换速度与质量并存!

MP4视频格式具有兼容性强、视频画质高清、文件体积较小、支持多种编码等特点,适用于网络媒体传播。如果大家想要将非MP4格式的视频转换成MP4的视频格式的话,可以使用MP4格式转换器更换格式。本文分别从...