⑤ 同步派发任务(syncDispatch)
就是一个同步进行的线程,下面由globalTaskDispatcher来派发同步任务。
修改MainAbility。
//日记
private static final HiLogLabel label = new HiLogLabel(3, 0xD001100, “ThreadDemo”);
private TaskDispatcher globalTaskDispatcher;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
//获取全局并发任务分发器 一个应用步伐只有一个
globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
//GlobalTaskDispatcher 派发同步任务
syncTask();
}
syncTask方法中中派发三个同步任务,打印日记
/**
- GlobalTaskDispatcher 派发同步任务
*/
private void syncTask() {
globalTaskDispatcher.syncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(label, “sync task1 run”);
}
});
HiLog.info(label, “after sync task1”);
globalTaskDispatcher.syncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(label,“sync task2 run”);
}
});
HiLog.info(label,“after sync task2”);
globalTaskDispatcher.syncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(label,“sync task3 run”);
}
});
HiLog.info(label,“after sync task3”);
}
运行之后,日记如下所示:
虽然现在是没有题目,但是如果对 syncDispatch 利用不妥, 将会导致死锁。如下情况大概导致死锁发生:
- 在专有线程上,利用该专有任务分发器进行 syncDispatch。
- 在被某个串行任务分发器(dispatcher_a)派发的任务中,再次利用同一个串行任务分发器(dispatcher_a)对象派发任务。
- 在被某个串行任务分发器(dispatcher_a)派发的任务中,经过数次派发任务,最终又利用该(dispatcher_a)串行任务分发器派发任务。例如:dispatcher_a 派发的任务利用 dispatcher_b 进行任务的派发,在 dispatcher_b 派发的任务中又利用 dispatcher_a 进行派发任务。
- 串行任务分发器(dispatcher_a)派发的任务中利用串行任务分发器(dispatcher_b)进行同步派发任务,同时dispatcher_b 派发的任务中利用串行任务分发器(dispatcher_a)进行同步派发任务。在特定的线程执行次序下将导致死锁。
⑥ 异步派发任务(asyncDispatch)
新写一个asyncTask方法,内里的内容和syncTask差不多。
/**
- GlobalTaskDispatcher 派发同步任务
*/
private void asyncTask() {
globalTaskDispatcher.asyncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(label,“sync task1 run”);
}
});
HiLog.info(label,“after sync task1”);
}
然后在onStart中调用即可
然后再运行。
同时这个异步派发是任务是可以取消的。Revocable,globalTaskDispatcher.asyncDispatch的返回值就是Revocable,
那么上面async中的代码就可以如许写。如下所示:
/**
- GlobalTaskDispatcher 派发同步任务
*/
private void asyncTask() {
Revocable revocable = globalTaskDispatcher.asyncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(label, “async task1 run”);
}
});
//撤销任务分发
revocable.revoke();
HiLog.info(label, “after async task1”);
}
在运行一下:
很显着内里的任务已经撤销了、
⑦ 异步延迟派发任务(delayDispatch)
异步延迟派发任务:异步执行,函数立即返回,内部会在延时指定时间后将任务派发到相应队列中。延时时间参数仅代表在这段时间以后任务分发器会将任务加入到队列中,任务的实际执行时间大概晚于这个时间。具体比这个数值晚多久,取决于队列及内部线程池的繁忙环境。下面用代码演示一下:
/**
*/
final long currentTime = System.currentTimeMillis();
/**
*/
final long delayTime = 100;
delayTask方法如下:
/**
- GlobalTaskDispatcher 派发异步延时任务
*/
private void delayTask() {
globalTaskDispatcher.delayDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(label, “delay task1 run”);
final long actualDelayMs = System.currentTimeMillis() - currentTime;
HiLog.info(label,"actualDelayTime >= delayTime : " + (actualDelayMs >= delayTime));
}
},delayTime);
HiLog.info(label, “after delay task1”);
}
日记如下:
⑧ 任务组(Group)
表示一组任务,且该组任务之间有肯定的联系,由 TaskDispatcher 执行createDispatchGroup 创建并返回,代码如下所示。
/**
*/
private void taskGroup(Context context) {
//创建并发任务分发器
TaskDispatcher dispatcher = context.createParallelTaskDispatcher(“parallelTaskDispatcher”, TaskPriority.DEFAULT);
//创建任务组
Group group = dispatcher.createDispatchGroup();
// 将任务 1 加入任务组,
dispatcher.asyncGroupDispatch(group,new Runnable() {
@Override
public void run() {
HiLog.info(label,“download task1 is running”);
}
});
// 将任务 2 加入任务组,
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(label,“download task2 is running”);
}
});
// 在任务组中的所有任务执行完成后执行指定任务。
dispatcher.groupDispatchNotify(group, new Runnable() {
@Override
public void run() {
HiLog.info(label, “the close task is running after all tasks in the group are completed”);
}
});
}
onStart方法中调用
运行效果如下,我运行了两次,两越日记是不一样的,如果内里执行的业务是不一样的,则耗时长的后完成。
⑨ 取消任务(Revocable)
Revocable 是取消一个异步任务的接口。异步任务包罗通过 asyncDispatch、delayDispatch、asyncGroupDispatch 派发的任务。如果任务已经在执行中或执行完成,则会返回取消散败。
/**
*/
private void revocableAsyncTask(Context context) {
TaskDispatcher dispatcher = context.getUITaskDispatcher();
Revocable revocable = dispatcher.delayDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(label, “delay dispatch”);
}
}, 10);
boolean revoked = revocable.revoke();
HiLog.info(label, “” + revoked);
}
在onStart()中调用
//取消异步任务
revocableAsyncTask(MainAbility.this);
运行效果如下:
⑩ 同步设置屏障任务 (syncDispatchBarrier)
在任务组上设立任务执行屏障,同步等待任务组中的所有任务执行完成,再执行指定任务。在全局并发任务分发器(GlobalTaskDispatcher)上同步设置任务屏障,将不会起到屏障作用。就比如说测验提前交卷,A提前20分钟,B提前10分钟,但你只是脱离了考室,离不开考场,这个考场的门就是这个屏障,无论你是提前多久,你都要等到所有考生考完,老师收卷之后才能脱离考场,就是这么一个理。代码如下:
/**
*/
private void setSyncDispatchBarrier(Context context) {
TaskDispatcher dispatcher = context.createParallelTaskDispatcher(“parallelTask”,TaskPriority.DEFAULT);
//创建任务组
Group group = dispatcher.createDispatchGroup();
//将任务1加入任务组
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(label,“task1 is running”);
}
});
//将任务2加入任务组
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(label,“task2 is running”);
}
});
dispatcher.asyncDispatchBarrier(new Runnable() {
@Override
public void run() {
HiLog.info(label,“Barrier”);
}
});
HiLog.info(label,“after syncDispatchBarrier”);
}
在onStart()中调用,
//同步设置屏障任务
setSyncDispatchBarrier(MainAbility.this);
运行
⑪ 异步设置屏障任务 (asyncDispatchBarrier)
在任务组上设立任务执行屏障后直接返回,指定任务将在任务组中的所有任务执行完成后再执行。在全局并发任务分发器(GlobalTaskDispatcher)上异步设置任务屏障,将不会起到屏障作用。可以利用并发任务分发器(ParallelTaskDispatcher)分离差异的任务组,达到微观并行、宏观串行的行为。
/**
*/
private void setAsyncDispatchBarrier(Context context) {
TaskDispatcher dispatcher = context.createParallelTaskDispatcher(“AsyncParallelTaskDispatcher”, TaskPriority.DEFAULT);
// 创建任务组
Group group = dispatcher.createDispatchGroup();
//将任务1加入任务组
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(label, “task1 is running”); // 1
}
});
//将任务2加入任务组
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(label, “task2 is running”); // 2
}
});
dispatcher.asyncDispatchBarrier(new Runnable() {
@Override
public void run() {
HiLog.info(label, “barrier”); // 3
}
});
HiLog.info(label, “after syncDispatchBarrier”); // 4
}
在onStart()中调用
//异步设置屏障任务
setAsyncDispatchBarrier(MainAbility.this);
运行效果
⑫ 执行多次任务(applyDispatch)
对指定任务执行多次
/**
*/
private void multipleTasks() {
//总执行次数
final int total = 10;
//倒数计时器
final CountDownLatch latch = new CountDownLatch(total);
//长整形列表数组
final ArrayList indexList = new ArrayList<>(total);
TaskDispatcher dispatcher = createParallelTaskDispatcher(“dispatcher”,
TaskPriority.DEFAULT);
//执行多次任务
dispatcher.applyDispatch((index) -> {
indexList.add(index);
latch.countDown();
HiLog.info(label, "long: "+index);
}, total);
//设置任务超时
try {
latch.await();
} catch (InterruptedException e) {
HiLog.info(label, “latch exception”);
}
//返回true则分析执行了10次
HiLog.info(label, “list size matches,” + (total == indexList.size()));
}
运行效果如下:
三、线程通信
在开发过程中,开发者经常需要在当前线程中处理下载任务等较为耗时的操作,但是又不希望当前的线程受到壅闭。此时,就可以利用 EventHandler 机制。EventHandler 是HarmonyOS 用于处理线程间通信的一种机制,可以通过 EventRunner 创建新线程,将耗时的操作放到新线程上执行。如许既不壅闭原来的线程,任务又可以得到合理的处理。比如:主线程利用 EventHandler 创建子线程,子线程做耗时的下载图片操作,下载完成后,子线程通过 EventHandler 关照主线程,主线程再更新 UI。
① EventRunner
EventRunner 是一种事件循环器,循环处理从该 EventRunner 创建的新线程的事件队列中获取 InnerEvent 事件或者 Runnable 任务。InnerEvent 是 EventHandler 投递的事件。
EventHandler 是一种用户在当前线程上投递 InnerEvent 事件或者 Runnable 任务到异步线程上处理的机制。每一个 EventHandler 和指定的 EventRunner 所创建的新线程绑定,并且该新线程内部有一个事件队列。EventHandler 可以投递指定的 InnerEvent 事件或 Runnable 任务到这个事件队列。EventRunner 从事件队列里循环地取出事件,如果取出的事件是InnerEvent 事件,将在 EventRunner 所在线程执行 processEvent 回调;如果取出的事件是Runnable 任务,将在 EventRunner 所在线程执行 Runnable 的 run 回调。
② EventHandler
EventHandler 有两个主要作用:
- 在差异线程间分发和处理 InnerEvent 事件或 Runnable 任务。
- 延迟处理 InnerEvent 事件或 Runnable 任务。
EventHandler 的运作机制如下图所示:
利用 EventHandler 实现线程间通信的主要流程:
- EventHandler 投递具体的 InnerEvent 事件或者 Runnable 任务到 EventRunner 所创建的线程的事件队列。
- EventRunner 循环从事件队列中获取 InnerEvent 事件或者 Runnable 任务。
- 处理事件或任务:
① 如果 EventRunner 取出的事件为 InnerEvent 事件,则触发 EventHandler 的回调方法并触发 EventHandler 的处理方法,在新线程上处理该事件。
② 如果 EventRunner 取出的事件为 Runnable 任务,则 EventRunner 直接在新线程上处理 Runnable 任务。
1. 束缚限定
- 在进行线程间通信的时间,EventHandler 只能和 EventRunner 所创建的线程进行绑定,EventRunner 创建时需要判定是否创建成功,只有确保获取的 EventRunner 实例非空时,才可以利用 EventHandler 绑定 EventRunner。
- 一个 EventHandler 只能同时与一个 EventRunner 绑定,一个 EventRunner 上可以创建多个 EventHandler。
2. 开发场景
EventHandler 的主要功能是将 InnerEvent 事件或者 Runnable 任务投递到其他的线程进行处理,其利用的场景包罗
- 开发者需要将 InnerEvent 事件投递到新的线程,按照优先级和延时进行处理。投递时,EventHandler 的优先级可在IMMEDIATE、HIGH、LOW、IDLE 中选择,并设置符合的 delayTime。
- 开发者需要将 Runnable 任务投递到新的线程,并按照优先级和延时进行处理。投递时,EventHandler 的优先级可在IMMEDIATE、HIGH、LOW、IDLE 中选择,并设置符合的 delayTime。
- 开发者需要在新创建的线程里投递事件到原线程进行处理。
3. 工作模式
EventRunner 的工作模式可以分为托管模式和手动模式。两种模式是在调用 EventRunner 的create()方法时,通过选择差异的参数来实现的,默以为托管模式。
- 托管模式:不需要开发者调用 run()和 stop()方法去启动和制止 EventRunner。当 EventRunner 实例化时,体系调用
run()来启动 EventRunner;当 EventRunner 不被引用时,体系调用 stop()来制止 EventRunner。
- 手动模式:需要开发者自行调用 EventRunner 的 run()方法和 stop()方法来确保线程的启动和制止。
③ 接口分析
1. EventHandler
- EventHandler 的属性 Priority(优先级)先容:
EventRunner 将根据优先级的高低从事件队列中获取事件或者 Runnable 任务进行处理。
| 属性 | 形貌 |
| — | — |
| Priority.IMMEDIATE | 表示事件被立即投递 |
| Priority.HIGH | 表示事件先于 LOW 优先级投递 |
| Priority.LOW | 表示事件优于 IDLE 优先级投递,事件的默认优先级是 LOW |
| Priority.IDLE | 表示在没有其他事件的环境下,才投递该事件 |
| 接口名 | 形貌 |
| — | — |
| 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) | 是否有还未被处理的这个任务 |
2. EventRunner
| 接口名 | 形貌 |
| — | — |
| create() | 创建一个拥有新线程的 EventRunner |
| create(boolean isDeposited) | 创建一个拥有新线程的 EventRunner,isDeposited 为 true 时,EventRunner 为托管模式,体系将主动管理该 EventRunner;isDeposited 为 false 时,EventRunner 为手动模式。 |
| create(String newThreadName) | 创建一个拥有新线程的 EventRunner, 新线程的名字是 newThreadName |
| current() | 获取当前线程的 EventRunner |
| run() | EventRunner 为手动模式时,调用该方法启动新的线程 |
| stop() | EventRunner 为手动模式时,调用该方法制止新的线程 |
3. InnerEvent
| 属性 | 形貌 |
| — | — |
| eventId | 事件的 ID, 由开发者定义用来辨别事件 |
| object | 事件携带的 Object 信息 |
| param | 事件携带的 long 型数据 |
| 接口名 | 形貌 |
| — | — |
| 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 |
④ 开发步调
一、EventHandler 投递 InnerEvent 事件
EventHandler 投递 InnerEvent 事件,并按照优先级和延时进行处理,创建一个MyEventHandler类型继承EventHandler
package com.llw.thread.event;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
public class MyEventHandler extends EventHandler {
/**
*/
private static final HiLogLabel label = new HiLogLabel(3, 0xD001100, “ThreadDemo”);
public MyEventHandler(EventRunner runner) throws IllegalArgumentException {
super(runner);
}
/**
- 创建 EventHandler 的子类,在子类中重写实现方法 processEvent()来处理事件
- @param event
*/
@Override
protected void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) {
return;
}
int eventId = event.eventId;
long param = event.param;
switch ((int) (eventId | param)) {
case 1:
HiLog.info(label, “eventId | param —>” + 1);
break;
default:
break;
}
}
/**
- EventHandler 投递 InnerEvent 事件
*/
private void initInnerEvent() {
//2. 创建 EventRunner,以手动模式为例。
// create()的参数是 true 时,则为托管模式
EventRunner runner = EventRunner.create(false);
if (runner == null) {
return;
}
//3. 创建 EventHandler 子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
//4. 获取 InnerEvent 事件。
int eventId1 = 0;
int eventId2 = 1;
long param = 0;
Object object = null;
InnerEvent event1 = InnerEvent.get(eventId1, param, object);
InnerEvent event2 = InnerEvent.get(eventId2, param, object);
//5. 投递事件,投递的优先级以 IMMEDIATE 为例,延时选择 0ms 和 2ms。
myHandler.sendEvent(event1, 0, EventHandler.Priority.IMMEDIATE);
// 延时 2ms 后立即处理
myHandler.sendEvent(event2, 2, EventHandler.Priority.IMMEDIATE);
//6. 启动和制止 EventRunner,如果为托管模式,则不需要此步调。
runner.run();
//待执行操作
// … 执行业务逻辑
// 制止 EventRunner
runner.stop();
}
}
二、EventHandler 投递 Runnable 任务
/**
- EventHandler 投递 Runnable 任务
*/
private void initRunnable() {
//2. 创建 EventRunner,以手动模式为例。
// create()的参数是 true 时,则为托管模式
EventRunner runner = EventRunner.create(false);
if (runner == null) {
return;
}
//3. 创建 EventHandler 子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
//2. 创建 Runnable 任务。
Runnable task1 = new Runnable() {
@Override
public void run() {
HiLog.info(label, “task1 running”);
}
};
Runnable task2 = new Runnable() {
@Override
public void run() {
HiLog.info(label, “task1 running”);
}
};
//3. 投递 Runnable 任务,投递的优先级以 IMMEDIATE 为例,延时选择 0ms 和 2ms。
myHandler.postTask(task1, 0, EventHandler.Priority.IMMEDIATE);
// 延时 2ms 后立即执行
myHandler.postTask(task2, 2, EventHandler.Priority.IMMEDIATE);
//4. 启动和制止 EventRunner,如果是托管模式,则不需要此步调。
runner.run();
//待执行操作
// … 执行业务逻辑
// 制止 EventRunner
runner.stop();
}
三、在新创建的线程里投递事件到原线程
修改MyEventHandler之后代码如下:
package com.llw.thread.event;
如何做好面试突击,规划学习方向?
面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平语言。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,碰到题目时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提拔。建议先订定学习操持,根据学习操持把知识点关联起来,形成一个体系化的知识体系。
学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提拔是很慢的。
同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精神),包含知识脉络 + 分支细节。
在搭建这些技术框架的时间,还整理了体系的高级进阶教程,会比自己碎片化学习效果强太多。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,碰到题目时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提拔。希望这份体系化的技术体系对大家有一个方向参考。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
g.info(label, “task1 running”);
}
};
Runnable task2 = new Runnable() {
@Override
public void run() {
HiLog.info(label, “task1 running”);
}
};
//3. 投递 Runnable 任务,投递的优先级以 IMMEDIATE 为例,延时选择 0ms 和 2ms。
myHandler.postTask(task1, 0, EventHandler.Priority.IMMEDIATE);
// 延时 2ms 后立即执行
myHandler.postTask(task2, 2, EventHandler.Priority.IMMEDIATE);
//4. 启动和制止 EventRunner,如果是托管模式,则不需要此步调。
runner.run();
//待执行操作
// … 执行业务逻辑
// 制止 EventRunner
runner.stop();
}
三、在新创建的线程里投递事件到原线程
修改MyEventHandler之后代码如下:
package com.llw.thread.event;
如何做好面试突击,规划学习方向?
面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平语言。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,碰到题目时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提拔。建议先订定学习操持,根据学习操持把知识点关联起来,形成一个体系化的知识体系。
学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提拔是很慢的。
同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精神),包含知识脉络 + 分支细节。
[外链图片转存中…(img-ruEi1L3d-1715435549328)]
在搭建这些技术框架的时间,还整理了体系的高级进阶教程,会比自己碎片化学习效果强太多。
[外链图片转存中…(img-H8y0nlLe-1715435549330)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,碰到题目时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提拔。希望这份体系化的技术体系对大家有一个方向参考。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |