Android多线程Handler的使用,基于源代码理解。

来源:互联网 发布:淘宝购物车需求分析 编辑:程序博客网 时间:2024/06/05 19:12

第一次接触Handler的时候一头雾水,当时学到了一半就没有再去接触了,这几天又潜下心来细细的研究了一下,根据Mars的视频和自己的理解。在理解Handler的同时,我们也需要理解其它2个对象。分别是:Looper、Message。
Looper,顾名思义,就是一个循环器,是Handler多线程中重要一环,他的作用主要有以下几点:
1、产生MessageQueue对象对象。在实例化Looper对象的时候,会同时实例化一个MessageQueue对象。
2、取出Message对象,并把取出的Message对象交给先前与Looper相关联的Handler对象。
Message,即消息。这就是我们Handler花九牛二虎之力需要“搬迁”到其它线程的对象。细细看看Android源代码,发现其实他的作用主要也有两点:
1、存放需要传输的数据,如使用Message的obj属性等。
2、关联使用了sendMessage方法的对象。[目的是为了在主线程中和使用handMessage方法的Handler一致]
以上都是我个人的理解,可能有办法有误,小伙伴们可以自己去看源码。SORRY...--.--
基于上面的理解,我们来梳理一般要如何使用Handler来处理多线程。总共方法有步:
1、初始化Looper。(这一步会产生MessageQueue对象)
2、实例化Handler。(这里要记住在哪个线程new 的Handler,Looper就在哪个线程运行)
3、启动Looper,即使Looper开始循环。
下面,我们基于Android源码来理解这三条。在这之前,大家要知道一点,在主线程中系统已经预设了一个Looper,所以主线程向其它线程发送消息时无需启动Looper,直接实例化Handler对象即可。

可以发现,其实实际方法就是三步。
第一步:Looper.prepare();

public static void prepare() {        prepare(true);    }    private static void prepare(boolean quitAllowed) { //实际是调用本方法。        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper(quitAllowed));    }

   sThreadLocal姑且可以理解为把new Looper(quitAllowed)存入当前线程。我们再来看看new Looper(quitAllowed)做了什么:

    private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);//实例化一个消息队列对象        mRun = true;        mThread = Thread.currentThread();    }

   总结第一步就是我们开始说的,实例化一个Looper和一个消息队列(MessageQueue)对象。

第二步:new Handler();

 public Handler() {        this(null, false);    }    public Handler(Callback callback, boolean async) {//实际构造函数是这个函数        if (FIND_POTENTIAL_LEAKS) {            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();//myLooper方法就是从当前线程中取出Looper对象(在Looper.prepare()中存进去的),并把其关联到Handler类中的Looper        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;//把开始初始化的消息队列关联到Hander类中的队列        mCallback = callback;        mAsynchronous = async;    }
 这一步不再赘述,上面代码已经注释过了。总结以来就是使Handler与Looper和MessageQueue(消息队列)相关联,并且一一对应。
第三步:Looper.loop();

public static void loop() {        final Looper me = myLooper();//从当前线程中取出Looper对象        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        final MessageQueue queue = me.mQueue;       ...        for (;;) {  //死循环。不断从消息队列中取出Message对象,为空则阻塞。            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);//追究源码可以发现,其实就是回调handleMessage方法。   //msg.target就是一个Handler if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } .... } msg.recycle(); } }

Handler target; //Message类的成员
    public void dispatchMessage(Message msg) { //Handler类        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);//回调        }    }

      第三步总结起来就是使Looper循环,取出Message对象,并使用这个对象,来产生回调。即我们重写的handMessage方法。

   第一次写博文,格式就调了1个小时- -请大家海涵。^_^     


==========================================================================================================================================================

更新……我还想解释一下,为什么Handler把消息放到MessageQueue中,然后Looper.loop()取出的时候恰好是我们放进去的Handler。

Message msg = Handler.obtainMessage();

这个obtainMessage()其实是把操作它的Handler放到了Message的属性里的。请看源码:

    public final Message obtainMessage()    {        return Message.obtain(this);    }
再追踪Message的obtain方法:

    public static Message obtain(Handler h) {        Message m = obtain();        m.target = h; //上面已经说过了,这个m.target就是Hanler,这一步就恰好把Hanlder存入了Message中。        return m;    }
至于取出,大家可以看上面,在Looper对象中loop方法中
msg.target.dispatchMessage(msg);//这个msg.target不就是开始存进来Handler吗?



0 0