一. 原理简述

1.1 使用目的

在“当前线程的Looper中Message处理完成,处于空闲状态”这个时机下,触发调用。

1.2 使用方法

  1. 创建IdleHandler 并实现其queueIdle的方法,其中queueIdle方法里面为执行的具体内容;
  2. addIdleHandler即可;

1.3 要点罗列

  1. “处于空闲状态”的时机分为 确实没有待处理消息 + 有延时处理消息但还没到延时时间 两种;
  2. queueIdle方法需要返回boolean值,当返回为false时,只执行本次;当返回为true时,本次执行完且出现下次空闲状态的时候,会重复调用。也就是可以对返回的boolean分场景进行处理就可以达到是否循环调用等功能。
  3. 具体源码分析和使用demo请查看 四.参考内容

二. 场景诉求

特定事件E0触发期间(t0到t1),主线程中剥离E0所需的非必要消息(m0、m1、m2...),在t1结束后,再按优先级逐个处理先前被剥离的非必要信息。从而达到缩短E0所用耗时(t1-t0)的要求。

三. 实现方案

3.1 整体设计

图片说明

3.2 实现优先级排序

  1. 创建任务集合,用来存储延时任务。例如HashMap<Integer,Runnable>;
  2. 使用需要被延时执行的代码块使用runnable封装,当执行到的时候加入到任务集合中进行存储;在存储时,由key的大小来标记执行的优先级;
  3. 在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 封装工具化

  1. 封装单例类IdleHandlerUtil
  2. 提供接口,例如addIdleTasks();addIdleHandler();
// 示例:addIdleHandler(),放在Runnable中可以决定是否延时执行
private Runnable mAddIdleHandler = () -> Looper
.getMainLooper.getQueue().addIdleHandler(IdleHandler实例);

四. 参考内容

  1. https://www.cnblogs.com/mingfeng002/p/12091628.html
  2. https://www.jianshu.com/p/a1d945c4f5a6
  3. https://cloud.tencent.com/developer/article/1006147
  4. https://www.runoob.com/java/java-hashmap-keyset.html