android postDelayed实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android postDelayed实现相关的知识,希望对你有一定的参考价值。

参考技术A

2015-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实现的主要内容,如果未能解决你的问题,请参考以下文章

Android多线程——View.post()源码分析

android开发--多线程

Android中的几种多线程实现

android handler调用post方法阻塞

如何在 android studio 中正确使用 postDelayed()?

Android源码解析View.post()到底干了啥