android postDelayed实现
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android postDelayed实现相关的知识,希望对你有一定的参考价值。
参考技术A2015-01-18 12:00
在android中做延时处理一般用handler.postDelayed()和view.postDelayed(action,delay)来实现,view.postDelayed也是通过handlder.postDelayed来实现的,不过有一些特殊处理的地方。
handler处理延时逻辑是通过发送延时消息来处理的
sendMessageDelayed:
sendMessageAtTime:
将延时消息放入到消息队列中。SystemClock.uptimeMillis()是开机到现在的时间(毫秒),不包括睡眠的时间。不用System.currentTimeMillis()的原因是System.currentTimeMillis()的时间是可以被System.setCurrentTimeMillis修改的,如果被修改了则发生难以想象的后果。
enqueueMessage调用MessageQueue.enqueueMessage(msg,uptimeMillis)
此处会将传入的消息对象根据触发时间(when)插入到message queue中。然后判断是否要唤醒等待中的队列。
. 如果插在队列中间。说明该消息不需要马上处理,不需要由这个消息来唤醒队列。
. 如果插在队列头部(或者when=0),则表明要马上处理这个消息。如果当前队列正在堵塞,则需要唤醒它进行处理。
通过nativeWake方法唤醒队列。
looper执行MessageQueue中的消息:
只是调用了MessageQueue.next()方法。可能会阻塞。
该方法会先调用nativePollOnce阻塞,然后进入死循环。nativePollOnce()的作用类似与object.wait(),使用了native方法来对线程进行精确时间的唤醒,
如果head Message是有延迟而且延迟时间没到的(now < msg.when),计算下时间间隔(nextPollTimeoutMillis),设置timeout为两者之差,进入下一次循环。
如果Message无延时或已到达执行时间,则直接返回该Message.
如果当前的Message阻塞住了MessageQueue(pendingIdleHandlerCount <= 0),把全局变量mBlocked改为true,在下一个Message放入队时会判断这个message的位置。如果在queue的头部,则用nativeWake唤醒线程。
总结:[msg loop] -->调用MessageQueue.next(),若头部的消息需要被执行在返回该消息,send该消息之后继续调用next方法获取下一个消息,若头部的不需要被执行则阻塞住队列,若有等待执行的Message,计算一下剩余时间,继续调用nativePollOnce()阻塞,无限循环到阻塞时间到或者下一次有Message进队。下个消息进队时若不需要延时在放在Queue的头部,否则在放在Queue的中部。
view的延时也是调用了handler的postDelayed.
若view的AttachInfo不为空,则调用AttachInfo中的handler的postDelayed。若AttachInfo为空,则先将action放入RunQueue中。RunQueue为HandlerActionQueue,用来存放view没有handler时的action。
执行action:
还是需要传入一个Handler,利用handler来执行action。当view被关联到window时,会执行该队列中的Action.
AttachInfo是View的一个附加信息存储类,当view被关联到window时会被赋值。
Android计时器
1.Handler类的postDelayed方法: Handler mHandler = new Handler(); Runnable r = new Runnable() { @Override public void run() { //do something //每隔1s循环执行run方法 mHandler.postDelayed(this, 1000); } }; 主线程中调用: mHandler.postDelayed(r, 100);//延时100毫秒 2.用handler+timer+timeTask方法: Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1){ //do something } super.handleMessage(msg); } }; Timer timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; 主线程中调用:timer.schedule(timerTask,1000,500);//延时1s,每隔500毫秒执行一次run方法 3.Thread+handler方法: Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1){ //do something } super.handleMessage(msg); } }; class MyThread extends Thread {//这里也可用Runnable接口实现 @Override public void run() { while (true){ try { Thread.sleep(1000);//每隔1s执行一次 Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); } catch (InterruptedException e) { e.printStackTrace(); } } } } 主线程中调用:new Thread(new MyThread()).start(); 二、三种延时的快捷方法: 1.Handler的postDelayed方法: new Handler().postDelayed(new Runnable() { @Override public void run() { //do something } }, 1000); //延时1s执行 2.timer + TimerTask方法: timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { //do something } },1000);//延时1s执行 3.Thread方法: new Thread(new MyThread()).start(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000);//延时1s //do something } catch (InterruptedException e) { e.printStackTrace(); } } }).start();
以上是关于android postDelayed实现的主要内容,如果未能解决你的问题,请参考以下文章