android开发分享android延迟执行优化(安卓开机自启动管理)idlehandler是什么?

首先,需要明确一点,handler 延时消息机制不是延时发送消息,而是延时去处理消息;举个例子,如下:

上述就是android开发分享android延迟执行优化安卓开机自启动管理)的全部内容,如果对大家有所用处且需要了解更多关于Android学习教程,希望大家多多关注—XD中文网(www.xdcnz.com)

handler.postdelayed(() ->{     log.e("zjt", "delay runnable"); }, 3_000); 

上面的 handler 不是延时3秒后再发送消息,而是将消息插入消息队列后等3秒后再去处理。

postdelayed 的方法如下:

public final boolean postdelayed(@nonnull runnable r, long delaymillis) {     return sendmessagedelayed(getpostmessage(r), delaymillis); } 

其中的 getpostmessage 就是将 post 的 runnable 包装成 message,如下:

private static message getpostmessage(runnable r) {     // 使用 message.obtain() 避免重复创建实例对象,达到节约内存的目的     message m = message.obtain();     m.callback = r;     return m; } 

sendmessagedelayed 方法如下:

public final boolean sendmessagedelayed(@nonnull message msg, long delaymillis) {     if (delaymillis 

sendmessageattime 如下:

public boolean sendmessageattime(@nonnull message msg, long uptimemillis) {     messagequeue queue = mqueue;     if (queue == null) {         runtimeexception e = new runtimeexception(                 this + " sendmessageattime() called with no mqueue");         log.w("looper", e.getmessage(), e);         return false;     }     return enqueuemessage(queue, msg, uptimemillis); } 

这里面的代码很好理解,就不说了,看看 enqueuemessage:

private boolean enqueuemessage(@nonnull messagequeue queue, @nonnull message msg,         long uptimemillis) {     msg.target = this; // 设置 msg 的 target 为handler     msg.worksourceuid = threadlocalworksource.getuid();     // 异步消息,这个需要配合同步屏障来使用,可以看我之前的文章,这里不赘述     if (masynchronous) {          msg.setasynchronous(true);     }     // 插入到 messagequeue 中     return queue.enqueuemessage(msg, uptimemillis); } 

messagequeue 的 enqueuemessage 的方法如下:

boolean enqueuemessage(message msg, long when) {     if (msg.target == null) {         throw new illegalargumentexception("message must have a target.");     }     if (msg.isinuse()) {         throw new illegalstateexception(msg + " this message is already in use.");     }     synchronized (this) {         // 判断发送消息的进程是否还活着         if (mquitting) {             illegalstateexception e = new illegalstateexception(                     msg.target + " sending message to a handler on a dead thread");             log.w(tag, e.getmessage(), e);             msg.recycle(); // 回收消息到消息池             return false;         }         msg.markinuse(); // 标记消息正在使用         msg.when = when;          message p = mmessages; // 获取表头消息         boolean needwake;         // 如果队列中没有消息 或者 消息为即时消息 或者 表头消息时间大于当前消息的延时时间         if (p == null || when == 0 || when 

举个例子,假设我们消息队列是空的,然后我发送一个延时10s的延时消息,那么会直接把消息存入消息队列。

从消息队列中获取消息是 通过 looper.loop() 来调用 messagequeue 的 next()方法,next()的主要代码如下:

 message next() {      // return here if the message loop has already quit and been disposed.      // this can happen if the application tries to restart a looper after quit      // which is not supported.      final long ptr = mptr;      if (ptr == 0) {          return null;      }      int pendingidlehandlercount = -1; // -1 only during first iteration      int nextpolltimeoutmillis = 0;      for (;;) {          if (nextpolltimeoutmillis != 0) {              binder.flushpendingcommands();          }          // 表示要休眠多长时间,功能类似于wait(time)          // -1表示一直休眠,          // 等于0时,不堵塞          // 当有新的消息来时,如果handler对应的线程是阻塞的,那么会唤醒          nativepollonce(ptr, nextpolltimeoutmillis);          synchronized (this) {              // try to retrieve the next message.  return if found.              final long now = systemclock.uptimemillis();              message prevmsg = null;              message msg = mmessages;              if (msg != null && msg.target == null) {                  // stalled by a barrier.  find the next asynchronous message in the queue.                  do {                      prevmsg = msg;                      msg = msg.next;                  } while (msg != null && !msg.isasynchronous());              }              if (msg != null) {                  if (now 

其实,从这里就可以看出来,handler 的延时消息是如何实现的了。

比方说 发送一个延时10s的消息,那么在 next()方法是,会阻塞 (10s + 发送消息时的系统开机时间 – 执行next()方法是系统的开机时间),到达阻塞时间时会唤醒。或者这时候有新的消息来了也会 根据 mblocked = true来唤醒。

idlehandler是什么?

在 messagequeue 类中有一个 static 的接口 idlehanlder:

public static interface idlehandler {     boolean queueidle(); } 

messagequeue中无可处理的message时回调; 作用:ui线程处理完所有事务后,回调一些额外的操作,且不会堵塞主进程;

接口中只有一个 queueidle() 函数,线程进入堵塞时执行的额外操作可以写这里, 返回值是true的话,执行完此方法后还会保留这个idlehandler,否则删除。

本文链接:https://xdcnz.com/9076.html