乐趣区

关于harmonyos:线程通信EventHandler使用

作者:韩茹

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

鸿蒙巴士专栏作家

一、应用场景

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:

退出移动版