一. 原理简述
1.1 使用目的
在“当前线程的Looper中Message处理完成,处于空闲状态”这个时机下,触发调用。
1.2 使用方法
- 创建IdleHandler 并实现其queueIdle的方法,其中queueIdle方法里面为执行的具体内容;
- addIdleHandler即可;
1.3 要点罗列
- “处于空闲状态”的时机分为 确实没有待处理消息 + 有延时处理消息但还没到延时时间 两种;
- queueIdle方法需要返回boolean值,当返回为false时,只执行本次;当返回为true时,本次执行完且出现下次空闲状态的时候,会重复调用。也就是可以对返回的boolean分场景进行处理就可以达到是否循环调用等功能。
- 具体源码分析和使用demo请查看 四.参考内容
二. 场景诉求
特定事件E0触发期间(t0到t1),主线程中剥离E0所需的非必要消息(m0、m1、m2...),在t1结束后,再按优先级逐个处理先前被剥离的非必要信息。从而达到缩短E0所用耗时(t1-t0)的要求。
三. 实现方案
3.1 整体设计
3.2 实现优先级排序
- 创建任务集合,用来存储延时任务。例如HashMap<Integer,Runnable>;
- 使用需要被延时执行的代码块使用runnable封装,当执行到的时候加入到任务集合中进行存储;在存储时,由key的大小来标记执行的优先级;
- 在queueIdle回调中执行时,取出map的key的大小来进行排序,逐个执行runnable;
// 添加任务 private HashMap<Integer,Runnable> mIdleTask = new HashMap<>(); public void addIdleTask(Runnable r,int importance) { synchronized (mIdleTask) { mIdleTask.put(importance,r); } } // 取出任务执行 @Override public boolean queueIdle() { synchronized (mIdleTask) { // 根据keyset取出所有的importance // 使用TreeSet将importance排序,并使用first()取出最小值 r.run(); // remove(r); // 视情况决定return true or false; } } //接入方只需实现Runnable r,将待执行代码块放入其中即可;
3.3 IdleHandler使用
提供“当前线程的Looper中Message处理完成,处于空闲状态”这个时机,来执行暂缓的消息。
3.4 封装工具化
- 封装单例类IdleHandlerUtil
- 提供接口,例如addIdleTasks();addIdleHandler();
// 示例:addIdleHandler(),放在Runnable中可以决定是否延时执行 private Runnable mAddIdleHandler = () -> Looper .getMainLooper.getQueue().addIdleHandler(IdleHandler实例);