美文网首页
Handler机制的问题

Handler机制的问题

作者: Jannonx | 来源:发表于2016-10-17 15:49 被阅读81次

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

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

本文为楼主原创,转载请表明出处: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。

//Looper
public 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);
}
上面已经就这源码关键代码梳理了一遍,部分代码并不全面,请各位自行查看源码,这样更加深刻。

相关文章

  • Handler机制的问题

    Handler机制的问题相信很多人都遇到过这样的面试题。那为什么需要Handler呢,你们有反问过自己 || 面试...

  • Handler机制小结

    Handler笔记 什么是handler机制?handler机制的主要成员1、handler:负责发送处理消息2、...

  • 常见问题总结

    handler机制,使用时一般会遇到的问题有 在子线程中handler使用handler.senMessage等方...

  • Handler机制之十大拷问

    首先来看几个问题: Handler机制是什么.Handler、MessageQueue、Looper之间的关系及各...

  • 深入理解Handler机制之引路篇

    要想深入理解Handler机制,就要理解: Android为何要引入Handler机制? Handler机制究竟是...

  • Android 的消息机制

    Android 消息机制主要是指 Handler 的运行机制。 **Handler **Handler 的运行需要...

  • Android:Handler 机制和原理?

    一、Handler机制概述 Handler机制也可以说是消息机制,Handler的运行时需要MessageQueu...

  • Android的消息机制Handler

    Android的消息机制就是Handler的运行机制。 先研究明白以下3个问题,有助于对Handler有一个深入的...

  • Handler机制

    前言 前几天在面试时,被问到了handler机制相关的问题,由于之前对handler机制的了解只是停留在表面,自然...

  • Handler 的理解

    几个关于Handler 的思考问题 Handler 消息管理机制,如何管理事务?Handler在线程间如何通信?H...

网友评论

      本文标题:Handler机制的问题

      本文链接:https://www.haomeiwen.com/subject/noxzyttx.html