Handler机制的问题
相信很多人都遇到过这样的面试题。
那为什么需要Handler呢,你们有反问过自己 || 面试官吗?
看完这篇文章相信你下次去面试就能好好的刷一下面试官的气焰了(装逼),毕竟很多公司本身没有android开发人员,面试题都是网上找的,或者理解不深。

  1. 为什么要有Handler
  2. 从源码角度理解该机制

本文为楼主原创,转载请表明出处:http://blog.csdn.net/Suma_sun/article/details/51427312

Handler的由来

首先为什么需要Handler呢? ——因为UI更新只能在UI线程。
那为什么只能在UI线程更新UI呢?——因为Android是单线程模型。
那为什么Android是单线程模型?
那是因为如果任意线程都可以更新UI的话,线程安全问题处理起来会相当麻烦复杂,所以就规定了Android是单线程模型,只允许在UI线程更新UI操作。

Handler机制

Handler机制有几个核心类:Handler、Looper、Message、MessageQueue。
Handler机制是一个典型的生产者消费者模式——多个生产者,一个消费者,该模式是处理线程安全的一个经典模式,如果不了解的请自行查阅相关资料,不懂也没关系,并不影响接下来的内容。

关联Looper
首先我们常用的构造方法

/**     * Default constructor associates this handler with the        {@link Looper} for the current thread.     *     * If this thread does not have a looper, this handler won't be able to receive messages     * so an exception is thrown.     */    public Handler() {        this(null, false);    }

默认的构造器 new Handler() 会从当前线程获取Looper关联。
如何关联呢?

public Handler(Callback callback) {        this(callback, false);    }public Handler(Looper looper) {        this(looper, null, false);    } public Handler(Looper looper, Callback callback) {        this(looper, callback, false);    } 

下面这个构造是所有传入null Looper的归属

//默认不开启private static final boolean FIND_POTENTIAL_LEAKS = false;public Handler(Callback callback, boolean async) {        if (FIND_POTENTIAL_LEAKS) {            //当子类是匿名类 或者 是成员类 或者 本地类时            //并且不是静态类时进行打印            //获取该类的修饰符 & 静态修饰符常量,&位运算,将值转为二进制进行对位比较,当某一位都为1时该位结果为1,只要某位有一个为0时结果位为0            final Class<? extends Handler> klass = getClass();            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                     (klass.getModifiers() & Modifier.STATIC) == 0) {                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                    klass.getCanonicalName());            }            //用于警告开发者该类可能存在泄漏        }        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;        mCallback = callback;        mAsynchronous = async;    }

mLooper = Looper.myLooper();//关联Looper关键代码
//Return the Looper object associated with the current thread. Returns null if the calling thread is not associated with a Looper.
意思是返回当前线程的Looper对象,如果为空告知线程关联Looper
所以当我们在Activity中创建Handler没问题,而在子线程中创建会报错的原因就在这里

获取消息
在Looper中有一函数loop();该函数会一直轮循获取消息,直到没有消息返回退出。

        //......        for (;;) {        //......            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            // This must be in a local variable, in case a UI event sets the logger            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            ......            }

在MessageQueue中找到next()方法

Message next() {    //......    for(;;){    //......    if (msg != null) {                    if (now < msg.when) {                        // Next message is not ready.  Set a timeout to wake up when it is ready.                        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 (false) Log.v("MessageQueue", "Returning message: " + msg);                        return msg;                    }                }        }} else {                    // No more messages.                    nextPollTimeoutMillis = -1;                }                // Process the quit message now that all pending messages have been handled.                if (mQuitting) {                    dispose();                    return null;                }         //......          }             

该方法也是一个轮循,并且是带同步块的操作,直到返回Message,或者调用quit(boolean safe)方法 改变mQuitting 使其返回null。

//Looperpublic void quit() {        mQueue.quit(false);    }

处理消息
获取到Message后会调用其持有的Handler对象dispatchMessage(msg)方法

msg.target.dispatchMessage(msg);

Message中找到如下代码

  Handler target;  Runnable callback;

Handler

/**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }

Handler收到消息后,先判断消息内的回调Runnable是否为空//post(Runnable)等方法
,为空就调用Handler内部的Runnable,

public Handler(Callback callback) {        this(callback, false);    }public Handler(Looper looper) {        this(looper, null, false);    }

然后调用handleMessage(msg);

public interface Callback {        public boolean handleMessage(Message msg);    }

上面已经就这源码关键代码梳理了一遍,部分代码并不全面,请各位自行查看源码,这样更加深刻。

更多相关文章

  1. Android(安卓)Handler解析
  2. Android退出程序(二)——利用广播机制
  3. Android-使用HttpURLConnection实现多线程下载
  4. AsyncTask 完全解析
  5. Android通知栏-Notification(通知消息)
  6. Intent 对象在 Android(安卓)开发中的应用
  7. Android(安卓)异常捕获
  8. view的绘制机制(一)
  9. android中对线程池的理解与使用

随机推荐

  1. Android Studio在Gradle中隐藏Keystore密
  2. Ubuntu10.04 32位编译Android 4.0源码
  3. Android定时器的使用,
  4. Android手势滑动(左滑和右滑)
  5. 用网络adb连接调试Android
  6. Android常见问题总结(七)
  7. Android BitmapShader 实战 实现圆形、圆
  8. android binder机制之--(我是Server Porxy
  9. IOS与Android的session的存储区别
  10. Android Activity生命周期