`
badpie
  • 浏览: 5557 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

Looper,MessageQueue,Message,Handler

阅读更多

 

先看看Looper,MessageQueue,Message,Handler之间的关系.

Looper,MessageQueue,Message,Handler之间的关系

Looper的构造函数是private,因此不能直接new,Looper的prepare方法会先检查当前线程下是否存在Looper,如果不存在则为当前线程new一个Looper,如果发现当前线程下已经存在Looper实例,则会抛出异常。

相关源码如下:

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    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可以简单理解为一个Map,一个以当前线程为key的Map。因此这样的初始化代码的意义就是为当前线程创建一个唯一的Looper实例。同样的道理,如果在同一个线程中多次调用Looper.prepare是会报错的。

Looper中还有一个比较常用的内容,先看源码

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

    public static Looper myLooper() {
        return sThreadLocal.get();
    }

乍一看起来上面这三个方法和prepare没啥区别,无非就是把为当前线程创建的Looper赋值给了sMainLooper类变量。实际上它也就是这个意思,没啥特别之处。唯一不同的是,Android系统在当前Application启动的时候(主线程中,也叫UI线程)自己调用了prepareMainLooper方法,这就导致了sMainLooper与UI线程产生绑定,带来的好处就是我们在自己的方法中(即使处于自定义子线程)可以使用getMainLooper来获得UI线程的Looper,让在这个Looper里的消息能处理UI内容。

 

接着需要看一下Handler的几个重要的构造函数干嘛了,相关源码:

    public Handler() {
        this(null, false);
    }

    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);
    }

    /**
     * @hide
     */
    public Handler(boolean async) {
        this(null, async);
    }

    /**
     * @hide
     */
    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();
        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;
    }

    /**
     * @hide
     */
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

  看得出来,构造函数主要就是指定一个Looper,缺省情况下使用当前线程对应的Looper。

那么Handler中的sendMessage方法做了些什么?看代码:

    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

 很简单,就是将当前Message派发给当前Looper中指定的MessageQueue.

 

是时候来看一个常用的例子了

package com.iteye.badpie.androidabc.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int MSG_HELLO = 100;
    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler = new Handler() {

            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case MSG_HELLO:
                    Log.d(TAG, String.format("handleMessage what:%s", "MSG_HELLO"));
                    break;

                default:
                    Log.d(TAG, String.format("handleMessage what:%s", msg.what));
                    break;
                }
            }

        };

        Message message = mHandler.obtainMessage(MSG_HELLO);
        mHandler.sendMessage(message);
    }

}

 运行结果:

D/MainActivity(  758): handleMessage what:MSG_HELLO

在主线程中运行的,因此可以在handlerMessage中处理UI内容,比如设置TextView的文字等等。

 

接着来看一个在自定义Thread中运行的例子

package com.iteye.badpie.androidabc.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int MSG_HELLO = 100;
    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new Thread("My Thread") {

            @Override
            public void run() {
                // 为这个子线程创建一个Looper
                Looper.prepare();
                mHandler = new Handler() {

                    @Override
                    public void handleMessage(Message msg) {
                        switch (msg.what) {
                        case MSG_HELLO:
                            Log.d(TAG, String.format("handleMessage what:%s, Looper:%s", "MSG_HELLO", Looper.myLooper().getThread().getName()));
                            break;

                        default:
                            Log.d(TAG, String.format("handleMessage what:%s, Looper:%s", msg.what, Looper.myLooper().getThread().getName()));
                            break;
                        }
                    }

                };

                Message message = mHandler.obtainMessage(MSG_HELLO);
                mHandler.sendMessage(message);

                // 让这个Looper驱动起来
                Looper.loop();
            }

        }.start();

    }

}

运行结果:

D/MainActivity(  927): handleMessage what:MSG_HELLO, Looper:My Thread
 

这个消息循环有问题,因为它不能结束。Looper.loop方法会一直运行,该方法在这个代码中不会返回。这可能需要一个变量来记录My Thread线程下的Looper,然后在需要时候调用其quit方法来结束消息循环。

可喜的是,针对这种问题Android提供了一个更方便的使用方法,看代码

package com.iteye.badpie.androidabc.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int MSG_HELLO = 100;
    private HandlerThread mHandlerThread;
    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandlerThread = new HandlerThread("Handler Thread");
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper()) {

            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case MSG_HELLO:
                    Log.d(TAG, String.format("handleMessage what:%s, Looper:%s", "MSG_HELLO", Looper.myLooper().getThread().getName()));
                    break;

                default:
                    Log.d(TAG, String.format("handleMessage what:%s, Looper:%s", msg.what, Looper.myLooper().getThread().getName()));
                    break;
                }
            }

        };

        Message message = mHandler.obtainMessage(MSG_HELLO);
        mHandler.sendMessage(message);

        // 结束消息循环时调用.最终会调用当前Looper中引用的MessageQueue的quit方法.
        // mHandlerThread.quit();
    }

}

 程序运行结果:

D/MainActivity( 1026): handleMessage what:MSG_HELLO, Looper:Handler Thread

 

附录

MessageQueue如何enqueue消息

    final boolean enqueueMessage(Message msg, long when) {
        if (msg.isInUse()) {
            throw new AndroidRuntimeException(msg + " This message is already in use.");
        }
        if (msg.target == null) {
            throw new AndroidRuntimeException("Message must have a target.");
        }

        boolean needWake;
        synchronized (this) {
            if (mQuiting) {
                RuntimeException e = new RuntimeException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
                return false;
            }

            msg.when = when;
            Message p = mMessages;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
        }
        if (needWake) {
            nativeWake(mPtr);
        }
        return true;
    }

看得出来,如果

p == null || when == 0 || when < p.when

会直接将消息放到链表的开始位置.所以在发送消息时使用如下方法会迅速将消息放到消息链表的开始位置:

    Message message = mHandler.obtainMessage(MSG_HELLO);
    mHandler.sendMessageAtTime(message, 0);
 
  • 大小: 40.9 KB
分享到:
评论

相关推荐

    Handler Looper MessageQueue 源码解析

    在Android系统中,Handler、Looper和MessageQueue是实现线程间通信的核心组件,它们共同构建了一个消息处理机制。本文将深入解析这三者的源码,帮助你理解它们的工作原理,并教你如何手写一套自己的Handler系统。 ...

    Handler+Looper+MessageQueue

    【Android 线程间通信:Handler、Looper 和 MessageQueue 深度解析】 在 Android 应用开发中,为了保证界面的流畅性,我们通常需要将耗时操作放在非 UI 线程中执行,然后通过某种机制将结果传递回 UI 线程进行界面...

    Thread,Looper,Handler,Message,MessageQueue,MessagePool之间的关系

    在Android系统中,线程(Thread)、Looper、Handler、Message以及MessageQueue和MessagePool是实现异步消息处理机制的关键组件,它们共同构建了一个高效的事件驱动模型。这些组件的关系紧密,协同工作,使得Android...

    Message,MessageQueue,Looper,Handler详解

    ### Message,MessageQueue,Looper,Handler详解 #### 一、几个关键概念 ##### 1、MessageQueue:消息队列 MessageQueue是一种数据结构,顾名思义,它充当了一个消息队列的角色,用来存放各种消息对象。每一个线程...

    handler与looper及messagequeue的简单总结

    在Android开发中,Handler、Looper和MessageQueue是用于实现线程间通信的关键组件,它们共同构建了一个消息处理机制。理解这三个概念以及它们之间的关系对于优化应用程序的性能和响应性至关重要。 Handler(处理器...

    Android 之 Looper、MessageQueue、Handler 与消息循环

    ### Android之Looper、MessageQueue、Handler与消息循环详解 #### 一、概述 在Android开发过程中,消息处理机制是至关重要的部分,它涉及到应用程序如何管理、传递和响应各种事件。本篇文章将深入探讨Android中...

    Android 异步处理 Handler+Looper+MessageQueue深入详解

    Handler、Looper和MessageQueue是Android异步处理机制中的核心组件,它们共同构建了一个消息传递系统,使得在不同线程间进行数据交换变得可能。下面我们将深入探讨这三个组件的工作原理及其在实际开发中的应用。 ...

    活用Android的Message Queue

    理解并熟练运用Message Queue、Looper和Handler是构建高效、响应性良好的Android应用的关键。 1. **Message Queue(消息队列)的角色** - 每个线程不自动创建Message Loop,需要手动通过Looper类来建立。 - ...

    Handler+Looper+MessageQueue+Message机制

    作用: 跨线程通信,异步通信。...MessageQueue(消息队列):由Looper负责管理,管理Handler发送过来的Message,其底层实现采用的是单链表。 Handler(处理者):负责Message的发送及处理。通过 Handler.send

    Message,MessageQueue,Looper,Handler详解[归类].pdf

    MessageQueue与Looper紧密配合,当MessageQueue中有新消息时,Looper会取出并分发给对应的Handler进行处理。主线程默认已经创建了MessageQueue和Looper,而在其他非主线程中,开发者需要手动调用`Looper.prepare()`...

    Android单线程模型中Message、Handler、Message Queue、Looper之间的关系---附实例源码

    Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理. 简单定义: 1、Message Queue(消息队列): 用来存放通过Handler发布的消息,通常...

    Looper,MessageQueue,Handler分析之ActivityThread.java

    Looper,MessageQueue,Handler分析之ActivityThread.java

    管理MessageQueue的Looper

    在Handler中,你可以发送一个Message到主线程的MessageQueue,主线程的Looper会接收到这个消息并调用Handler的`handleMessage()`,从而更新UI。 需要注意的是,每个线程只有一个Looper实例,且一旦调用`Looper.loop...

    管理MessageQueue的Looper使用

    首先,`Looper`是Android系统中一个用于处理消息循环的类,它在后台线程中不断检查消息队列`MessageQueue`,并将新消息分发给相应的`Handler`进行处理。通常,主线程(UI线程)已经有一个默认的`Looper`在运行,因此...

    深入Android Handler,MessageQueue与Looper关系

    深入 Android Handler,MessageQueue 与 Looper 关系 Android 消息机制是 Android 程序设计中非常重要的一部分,其中 Handler、MessageQueue 和 Looper 是三个紧密相关的概念。Handler 是 Android 消息机制的上层...

    android MessageQueue

    在Android系统中,MessageQueue是消息机制的核心组件之一,它与Handler、Looper紧密协作,用于实现线程间的通信。理解MessageQueue的工作原理对于优化应用程序性能和处理异步操作至关重要。 MessageQueue是一个内部...

    Android的消息处理机制--Message,MessageQueue

    4. **Looper**:充当MessageQueue和Handler之间的桥梁角色,负责循环取出MessageQueue中的消息,并交给对应的Handler处理。 #### 四、消息处理流程 1. **创建Handler**:每个需要处理消息的线程都需要一个Handler...

    AsyncTask陷阱之:Handler,Looper与MessageQueue的详解

    在Android开发中,`Handler`、`Looper`和`MessageQueue`是处理线程间通信的关键组件,特别是当涉及到UI更新时。这篇文章将深入解析这三个概念,以及它们在`AsyncTask`中的应用和潜在陷阱。 首先,`Handler`是...

    android线程 Handler Message Queue AsyncTask线程模型 线程交互 + 修改Button样式 示例 最终easy整合版

    - **Handler/Looper/Message Queue**:通过创建Handler对象,与主线程的Looper和Message Queue协同工作,实现异步消息处理。 - **AsyncTask**:简化了在后台线程执行任务并在UI线程更新结果的流程。 2. **Handler...

    android_os_MessageQueue.rar_android

    MessageQueue主要用于存储待处理的消息(Message)队列,这些消息通常由Handler创建并插入队列,然后由Looper取出并分发给相应的Handler进行处理。 1. **MessageQueue的生命周期**: - 创建:MessageQueue通常在...

Global site tag (gtag.js) - Google Analytics