Handler机制简介

Handler是android中最重要组成部分之一,Handler机制可以看做是一个消息阻塞队列,APP启动后很快就进入死循环(while循环),不断的读取消息队列中的消息,每个线程最多只有一个消息队列,没有消息时就阻塞,有就立马执行。所有消息排队执行,因为是一个线程,所以同时只能执行一个消息。android的view绘制,事件响应(点击,触摸屏幕等)都是把消息发送到了主线程的消息队列,等待android APP的执行(这点可以通过手动抛出异常查看错误堆栈来验证)。包括自己在主线程new 的handler最终也是把消息插入到了主线程消息队列中。从以上来看android主线程大部分时间是空闲的。当点击屏幕后手机能立马响应也可以看出android主线程大部分时间是空闲的。虽然主线程要处理的事情狠多,很杂,很琐碎(view布局、绘制,事件分发等等),但处理时间都很短暂,可以保证很快处理完毕,然后等待下一个消息的到来。android handler机制简可以实现所有view相关的操作都在主线程进行,从而避免了使用 锁 。具体实现代码 如下。

java工程实现Handler机制代码

下面的代码跟android的handler机制主要原理完全一致,但不依赖android系统。

import com.handler.Handler;import com.handler.Looper;import com.handler.Message;public class Main {    public static void main(String[] args) {        new Main().start();            }        private void start(){        //创建该线程唯一的消息队列,线程安全的阻塞队列        Looper.prepare();        onCreate();                //死循环,阻塞式,执行下面代码后主线程就会去获取消息队列里的消息,没有消息时就阻塞,有就执行。执行Looper.loop前即使消息队列里有消息,消息也不会执行,因为主线程还没有去检查消息队列。        Looper.loop();                //下面 的代码通常不会执行,除非手动让主线程消息队列退出。退出主线程消息队列后android的view布局、绘制,事件分发就不执行了,所以android APP也没必要继续执行了,所以android采用了抛出异常的方式结束APP。        System.out.println("exit........");        throw new RuntimeException("Main thread loop unexpectedly exited");    }    private void onCreate() {        //////////////////////////////////////////////////////////        ////// 下面的操作相当于运行在android的UI线程中 ////////////        //////////////////////////////////////////////////////////        final Thread thread = Thread.currentThread();        System.out.println("main thread=" + thread);        Handler handler = new Handler() {            @Override            public void handleMessage(Message msg) {                //若thread == Thread.currentThread(),则证明已经运行在主线程中了                System.out.println("current thread is main thread? " + (thread == Thread.currentThread()));                System.out.println(msg);                System.out.println();            }        };        // 测试1       主线程创建handler,子线程使用该handler发送消息         new Thread() {            public void run() {                try {//模拟耗时操作                    Thread.sleep(1000 * 2);                } catch (InterruptedException e) {                }                Message message = new Message();                message.obj = "new Thread" + Thread.currentThread();                message.what = (int) System.currentTimeMillis();                //在子线程中发送消息                 handler.sendMessage(message);                                try {                    Thread.sleep(1000 * 2);                } catch (InterruptedException e) {                }                                message = new Message();                message.obj = "hanler...waht==1" ;                message.what = 1;                //在子线程中发送消息                 handler.sendMessage(message);                                message = new Message();                message.obj = "hanler...waht==2" ;                message.what = 2;                //在子线程中发送消息                 handler.sendMessage(message);                                message = new Message();                message.obj = "hanler...waht==3" ;                message.what = 3;                //在子线程中发送消息                 handler.sendMessage(message);                            };        }.start();        // 测试2 在thread内部创建handler,结果会抛出异常        new Thread() {            public void run() {                try {                    sleep(1000 * 3);                } catch (InterruptedException e) {                }                /*                 * 在线程内部使用默认构造函数创建handler会抛出异常。                 * android中也可以在子线程中创建Handler,但要在初始化时传入Looper,                 * Looper.getMainLooper()获取到的就是主线程的Looper,所以可以这样创建                 *                  * new Handler(Looper.getMainLooper()){                        @Override                        public void handleMessage(Message msg) {                            //运行在主线程中                        }                    };                 */                Handler h = new Handler() {                    public void handleMessage(Message msg) {                        System.out.println("haneler msg...." + msg);                    };                };                Message message = new Message();                message.obj = "handler in new Thread";                message.what = (int) System.currentTimeMillis();                //在子线程中发送消息                 h.sendMessage(message);            };        }.start();        //////////////////////////////////////////////////////////        ////// 上面的操作相当于运行在android的UI线程中 ////////////        //////////////////////////////////////////////////////////    }}

运行结果

main thread=Thread[main,5,main]  current thread is main thread? true  what=18175614 obj=new ThreadThread[Thread-0,5,main]    Exception in thread "Thread-1" java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()      at com.handler.Handler.(Handler.java:14)      at Main$3$1.(Main.java:103)      at Main$3.run(Main.java:103)  current thread is main thread? true  what=1 obj=hanler...waht==1    current thread is main thread? true  what=2 obj=hanler...waht==2    current thread is main thread? true  what=3 obj=hanler...waht==3  

Handler代码

package com.handler;      public class Handler {          private MessageQueue messageQueue;            public Handler() {            Looper looper=Looper.myLooper();                    if (looper==null) {               throw new RuntimeException(                          "Can't create handler inside thread that has not called Looper.prepare()");                           }                    this.messageQueue=looper.messageQueue;      }        public void sendMessage(Message msg) {                    //Looper循环中发现message后,调用message.targer就得到了当前handler,使用taget.handleMessage          //就把消息转发给了发送message时的handler的handleMessage函数          msg.target=this;                    messageQueue.enqueueMessage(msg);                }            public void handleMessage(Message msg) {      }  }  

Looper代码

package com.handler;public class Looper {    private static final ThreadLocal threadLocal=new ThreadLocal<>();    /**     * 存储Message的队列,阻塞式,没有消息则一直等待     */    final MessageQueue messageQueue;            private Looper() {        messageQueue=new MessageQueue();    }    /**为该线程创建Looper,     * 若该线程已经有Looper了则不需要再次调用prepare     */    public  static void prepare() {        if (threadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        threadLocal.set(new Looper() );    }        public static void loop() {        Looper looper=myLooper();        if (looper == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        MessageQueue messageQueue=looper.messageQueue;                for(;;){            Message message=messageQueue.next();            message.target.handleMessage(message);        }    }        /**     * 获取当先线程的Looper     * @return     */    public static Looper myLooper() {        return threadLocal.get();    }}

MessageQueued代码

package com.handler;    import java.util.concurrent.BlockingQueue;  import java.util.concurrent.LinkedBlockingQueue;    public class MessageQueue {          private BlockingQueueblockingQueue=new LinkedBlockingQueue<>();            /**      * 阻塞式,没有消息则一直等待      * @return      */      public Message next() {          try {              return blockingQueue.take();          } catch (InterruptedException e) {              throw new RuntimeException();          }      }            /**      * 插入到消息队列尾部      * @param message      */      void enqueueMessage(Message message) {          try {              blockingQueue.put(message);          } catch (InterruptedException e) {              // TODO Auto-generated catch block              e.printStackTrace();          }      }  }  

ThreadLocal简单实现

ThreadLocal内部原理和下面实现方式不同,但达到的效果是相同的,本篇主要介绍Handler机制,简化了ThreadLocal

package com.handler;    import java.util.HashMap;  import java.util.Map;  /**  * ThreadLocal简单实现  * @author Young  *  * @param   */  public class ThreadLocal {          private Mapmap;        public ThreadLocal() {          map=new HashMap<>();      }            public void set(T obj) {          map.put(Thread.currentThread(),obj);      }            public T get() {          return map.get(Thread.currentThread());      }        }  

Message代码

package com.handler;    public class Message {        Handler target;      public Object obj;      public int what;        @Override      public String toString() {          return   "what="+what+" obj="+obj.toString();      }        }  

以上就是android Handler机制原理代码了。

android还提供了HandlerThread,其实是对Handler和Thread的封装。

先看一下HandlerThread使用方式

Handler myHandler; new HandlerThread("Compress-Thread") {              @Override              protected void onLooperPrepared() {                  super.onLooperPrepared();                  myHandler = new Handler();                  myHandler.post(new Runnable(){                   @Override                      public void run() {                                  //在HandlerThread线程执行                    }                                     });            }          }.start();//不要在这使用myHandler发送消息,因为myHandler是在onLooperPrepared中创建的,onLooperPrepared又是运行在HandlerThread线程的,所以刚执行到这时HandlerThread线程可能还没有创建完,onLooperPrepared也就不会执行,myHandler自然是null

每次new HandlerThread都会创建一个新线程,当我们使用myHandler发送消息时消息就会在HandlerThread线程执行。HandlerThread线程内部也是一个死循环,通常不会退出,当通过myHandler为其发送消息时就会从阻塞中醒来执行消息,执行完消息队列里的消息后就又阻塞。HandlerThread可以排队执行消息,保证能按加入消息的先后顺序执行。比如我们需要压缩很多图片时,就可以使用HandlerThread,主线程直接把图片通过myHandler发送到HandlerThread,HandlerThread就可以执行图片压缩,所有压缩任务都按添加顺序依次执行。

来自我的博客

http://blog.csdn.net/qingchunweiliang/article/details/50448365

END

更多相关文章

  1. Android之基于xmpp openfire smack开发之Android消息推送技术原
  2. 浅谈Android四大组件之BroadcastReceiver
  3. 浅谈:Android(安卓)TextView的append方法与滚动条同时使用
  4. 2020.8.12 京东Android开发工程师一面面经
  5. Android(安卓)intent消息通知机制
  6. android 中asynctask的一些研究
  7. Android中IntentService和HandlerThread的分析
  8. Android(安卓)4.0 input touch解析(一)
  9. Android跨进程通信IPC之3——Bionic

随机推荐

  1. Activity的四种启动模式和onNewIntent()
  2. RelativeLayout 属性
  3. 沉浸式状态栏StatusBar
  4. Android(安卓)Service 服务详细讲解
  5. Android的四种启动方式
  6. Handler机制情景分析
  7. Android应用程序与SurfaceFlinger服务之
  8. Android(安卓)Studio 下载安装教程
  9. android TextView 阴影效果,和使用style学
  10. Android禁止横屏竖屏切换