56星座屋
当前位置: 首页 星座百科

android延迟执行优化(安卓开机自启动管理)

时间:2023-06-07 作者: 小编 阅读量: 2 栏目名: 星座百科

首先,需要明确一点,Handler延时消息机制不是延时发送消息,而是延时去处理消息;举个例子,如下:,今天小编就来说说关于android延迟执行优化?下面更多详细答案一起来看看吧!

android延迟执行优化?首先,需要明确一点,Handler 延时消息机制不是延时发送消息,而是延时去处理消息;举个例子,如下:,今天小编就来说说关于android延迟执行优化?下面更多详细答案一起来看看吧!

android延迟执行优化

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

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 < 0) {delayMillis = 0;}// 延时的时间是手机的开机时间(不包括手机休眠时间)+ 需要延时的时间return sendMessageAtTime(msg, SystemClock.uptimeMillis() + 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 为Handlermsg.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 < p.when) {// New head, wake up the event queue if blocked.msg.next = p;mMessages = msg;// 表示要唤醒 Hander 对应的线程,这个后面解释needWake = mBlocked;} else {needWake = mBlocked && p.target == null && msg.isAsynchronous();Message prev;// 如下都是单链表尾插法,很简单,不赘述for (;;) {prev = p;p = p.next;if (p == null || when < p.when) {break;}if (needWake && p.isAsynchronous()) {needWake = false;}}msg.next = p; // invariant: p == prev.nextprev.next = msg;}// 唤醒Handler对应的线程if (needWake) {nativeWake(mPtr);}}return true;}

举个例子,假设我们消息队列是空的,然后我发送一个延时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 iterationint 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 < msg.when) { // 计算延时消息的剩余时间 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else { // Got a message. mBlocked = false; if (prevMsg != null) {prevMsg.next = msg.next; } else {mMessages = msg.next; } msg.next = null; if (DEBUG) Log.v(TAG, "Returning message: " + msg); msg.markInUse(); return msg;}} else {// No more messages.nextPollTimeoutMillis = -1;}.......// 判断是否有 idle 任务,即主线程空闲时需要执行的任务,这个下面说if (pendingIdleHandlerCount <= 0) {// 这里表示所有到时间的消息都执行完了,剩下的如果有消息一定是延时且时间还没到的消息;// 刚上面的 enqueueMessage 就是根据这个变量来判断是否要唤醒handler对应的线程mBlocked = true;continue;}......} }

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

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

IdleHandler是什么?

在 MessageQueue 类中有一个 static 的接口 IdleHanlder:

public static interface IdleHandler {boolean queueIdle();}

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

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

    推荐阅读
  • 送给父亲的一句话(送给父亲的暖心话语)

    我是神父,受您儿女们的嘱托,向您传送父亲节的祝福。父亲节马上要到了,愿你的父亲健康幸福!爸爸,父亲节快到了,这二十多年来,您为我付出的太多太多,我这辈子都是报答不完的,希望您每天都开开心心,健康平安。父爱如山,连绵而伟岸;父爱如水,刚与柔并济;父爱如风,无处而不在;父爱如光,灿烂而热烈;祝父亲节日快乐,健康幸福!即使不在我身边,那份浓浓的父爱仍然会帮助我,祝您父亲节快乐!

  • 一路长虹是什么意思(科普一路长虹的意思)

    下面更多详细答案一起来看看吧!一路长虹是什么意思一路长虹是指电视收视率越来越高。虹,意思是像彩虹那样长而灿烂,这个词语只是一个代表电视剧或者电影的一个收视率祝福语。一路长虹不是成语,一开始只在电视台内部人员之间流传及使用。另外,形容收视率高的成语还有万人空巷、万头攒动、无往不胜、战无不胜、座无虚席等。

  • 野菜不是你想吃随便就可以吃(野菜虽美味采食需慎重)

    所以购买或采摘时应选择新鲜幼嫩的香椿芽,并减少存放时间,尽快食用。尤其是过敏体质或患有一些慢性病的人群,尽量少吃或不吃香椿。另外,荠菜中草酸含量较高,食用之前建议焯水。有研究表明,马齿苋中含有较高含量的α-亚麻酸,同时含有多种功能性成分,具有一定的抗菌、抗病毒、抗肿瘤、降血脂、降血糖、抗衰老等作用。尤其老人、婴幼儿、孕产妇、哺乳期妇女、过敏体质人群,尽量少食或者不食用。

  • 人生海海山山而川不过尔尔啥意思(人生海海山山而川不过尔尔如何理解)

    接下来我们就一起去了解一下吧!人生海海山山而川不过尔尔啥意思意思是人生像大海一样茫然,总是起起落落,有很多不确定因素,走过平湖烟雨,跨过岁月山河,最终发现也不过如此。人生海海,生生而川出自麦家的《人生海海》,告诉人们人生总是会在没有任何约定的情况下就意外遇见温暖,还有持续不断的希望。鼓励人在任何情况下也不要放弃希望,因为希望绵延不断。也不要放弃对美好生活的追求,因为总有些温暖不期而遇。

  • 肛门瘙痒可以用红霉素软膏 肛门瘙痒可以用红霉素软膏擦吗

    红霉素软膏的主要作用皮肤感染作为抗生素类软膏,红霉素软膏首先用于治疗和预防皮肤感染。除了抗感染之外,红霉素软膏还有其它一些用途。轻微创伤如身体轻微挫伤、划伤或其它创伤都可使用红霉素软膏,一般用法是将患处清洗消毒,之后将适量药膏涂于患处,1日2次。口角炎口角炎多因感染引起,以学龄前儿童多见。细菌性口角炎可以涂抹少量红霉素软膏,同时服用维生素B2。

  • 计算机指令中的地址码指什么(计算机指令中的地址码是什么)

    计算机指令中的地址码指什么地址码和机器码是产品出厂时已经设定的号码,用以区别不同的设备,就如同机器的身份号。地址码一般为7位数,机器码为16位数。数字信息机和语音信息机采用的是地址码。可手动更改数字信息机的地址码,每台机器最多可设定7个地址码,详细操作请见说明书。

  • 烟台养老保险缴费基数是多少 烟台社保的缴费基数

    2022年烟台市社会保险缴费基数的上下限依据烟人社字﹝2022﹞95号文之规定,我市2022年度职工基本养老保险、失业保险、工伤保险个人月缴费基数的上限为19899元,下限为3980元。提高标准所需资金,由各地统筹中央、省级城乡居民基本养老保险补助资金予以落实。

  • 红毛丹的功效与作用(红毛丹的功效与作用简述)

    以下内容希望对你有帮助!红毛丹的功效与作用红毛丹的功效与作用如下。红毛丹有增强人体免疫力的作用:红毛丹果肉里含有的维生素可以让细胞的抵抗能力增强。红毛丹有滋养头皮发、护肤美肤的作用,长期使用一定量的红毛丹,能够让头发得到滋润,还可以补气血健美皮肤。红毛丹有清热解毒的作用:红毛丹可以清心去火、清热除燥,能够帮助人体消除血液中的热毒,而且红毛丹的树根熬煮后也是有此等功效的。

  • 2020年三水区公办初中积分入学录取工作安排

    填报时要上传积分申请人的户口簿本人页、学生本人页图片,非三水区学籍的学生,还要上传《学籍基本信息表》原件图片。入围录取的学生,根据三水区公办初中学位安排规则,以积分从高到低排名次序,参考个人志愿统筹安排学位。在8月4日前由分配的学校通知学生并完成注册工作。逾期注册视为放弃学位。至此,三水区公办初中招生录取工作全部结束。

  • 太极图的含义(太极图解释)

    太极图的含义太极图是我国古代说明宇宙现象的图,一种是用圆形的图像表示阴阳对立面的统一体,圆形外边附八卦方位,道教常用它做标志。另一种是宋周敦颐所画的,代表宋代理学对于世界形成问题的看法。《太极图》据传是宋朝道士陈抟所传出。周敦颐著《太极图说》加以解释。周敦颐“一方面从陈抟派道家易里吸收了太极图式说并与新的解释,另一方面继承了汉唐以来义理学派的传统成为宋明道学家解易的先驱。”