使用Handler和Thread是Android进行线程间通信的主要方式。具体方式是,在异步线程中,使用handler发送Message到指定队列(handler.sendMessage(Message msg))。目标队列接收消息后,将消息添加到队列中,Looper轮询队列,依次对异步线程发送过来的Message进行处理,下面结合Android源码详述。
先看Handler的构造方法(android.os.Handler.java):
public Handler() { //doSomething 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 = null; } /** * Constructor associates this handler with the queue for the * current thread and takes a callback interface in which you can handle * messages. */ public Handler(Callback callback) { //doSomething 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; } /** * Use the provided queue instead of the default one. */ public Handler(Looper looper) { mLooper = looper; mQueue = looper.mQueue; mCallback = null; } /** * Use the provided queue instead of the default one and take a callback * interface in which to handle messages. */ public Handler(Looper looper, Callback callback) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; }
每个handler必定有一个对应的Looper,如果没有在构造器中传入,则调用Looper.myLooper()生成一个默认的Looper,再去看Looper的代码(android.os.Looper.java):
// sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }
sThreadLocal里什么时候装进去的Looper呢?在android.app.ActivityThread.java代码里发现了对Looper的static方法的调用:
public static void main(String[] args) { SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
这个main方法在系统启动时已经被调用过,android.os.Looper.sThreadLocal是一个静态常量,所有Looper实例共用此常量。
/** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } /** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(); setMainLooper(myLooper()); myLooper().mQueue.mQuitAllowed = false; } private synchronized static void setMainLooper(Looper looper) { mMainLooper = looper; } /** Returns the application's main looper, which lives in the main thread of the application. */ public synchronized static Looper getMainLooper() { return mMainLooper; }
prepareMainLooper()方法调用了prepare()方法,prepare()方法为android.os.Looper.sThreadLocal进行赋值,我们继续跟进Looper的构造器:
private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }
至此,Looper和当前线程对应起来,并且实例化MessageQueue对象。
按以上,如果我们在主线程里不传Looper实例化了一个Handler,handler对应的Looper所对应的线程就是ActivitThread运行的线程,就是我们常说的主线程。
如果我们在非主线程里实例化了一个Looper,方法必然是在当前线程调用Looper.prepare(); Looper.loop();。Handler对应的Looper对应当前线程。
一个线程中可以创建多个Handler,但只能拥有一个Looper,一个Looper对应一个消息队列。
注:对同一个ThreadLocal对象调用get方法,不同线程将得到不同结果,具体原理与介绍不在此描述。
下面我们开始使用handler工作,发送消息时使用sendMessage方法或者Message的sendToTarget方法,最终都会调用到handler对应的Looper持有的MessageQueue,队列调用
final boolean enqueueMessage(Message msg, long when) { if (msg.isInUse()) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } final 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; } else if (msg.target == null) { mQuiting = true; } msg.when = when; //Log.d("MessageQueue", "Enqueing: " + msg); Message p = mMessages; if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; needWake = mBlocked; // new head, might need to wake up } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; needWake = false; // still waiting on head, no need to wake up } } if (needWake) { nativeWake(mPtr); } return true; }
这个方法把发送的Message添加到队列中,而已经启动的Looper则一直在轮询运行
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); while (true) { Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } long wallStart = 0; long threadStart = 0; // 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); wallStart = SystemClock.currentTimeMicro(); threadStart = SystemClock.currentThreadTimeMicro(); } msg.target.dispatchMessage(msg); if (logging != null) { long wallTime = SystemClock.currentTimeMicro() - wallStart; long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); if (logging instanceof Profiler) { ((Profiler) logging).profile(msg, wallStart, wallTime, threadStart, threadTime); } } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycle(); } } }
方法中msg.target.dispatchMessage(msg);说明handlder的dispatchMessage()方法运行在loop()调用的线程中,dispatchMessage方法将调用handleMessage方法。
这样,Handler处理消息的代码将运行在其对应的Looper所在的线程。整体的结构也就清晰了:
Handler实例化时,引用一个Looper,Looper唯一对应一个线程,Looper持有一个消息队列,Handler发送消息到消息队列,Looper轮询获取消息队列中的待处理Message,Message对象的target在轮询中顺次分发给Handler,Handler的handleMessage方法被调用。
相关推荐
【Android 线程间通信:Handler、Looper 和 MessageQueue 深度解析】 在 Android 应用开发中,为了保证界面的流畅性,我们通常需要将耗时操作放在非 UI 线程中执行,然后通过某种机制将结果传递回 UI 线程进行界面...
本文详细介绍了Android中消息处理机制的核心组件Looper、MessageQueue和Handler的工作原理及其实现细节。理解这些概念有助于开发者更好地设计和实现多线程应用程序,提高程序的性能和用户体验。通过合理利用这些组件...
综上所述,Message、MessageQueue、Looper和Handler这四个组件共同构成了Android应用程序中处理消息的基本机制。通过它们之间的相互协作,使得应用程序能够在不同的线程间高效地传递和处理消息,从而实现了复杂的...
理解Thread、Looper、Handler、Message、MessageQueue和MessagePool之间的关系对于优化Android应用的性能和响应速度至关重要。开发者需要熟练掌握这一机制,以便在多线程环境中正确处理异步任务,保证UI的流畅性。在...
在Android系统中,Handler、Looper和MessageQueue是实现线程间通信的核心组件,它们共同构建了一个消息处理机制。本文将深入解析这三者的源码,帮助你理解它们的工作原理,并教你如何手写一套自己的Handler系统。 ...
在Android开发中,Handler...总的来说,理解Handler、Looper和MessageQueue的关系以及它们在Android中的作用,是提升应用程序性能和用户体验的关键。熟练掌握这些组件,有助于编写出更加高效、响应迅速的Android应用。
理解并熟练运用Message Queue、Looper和Handler是构建高效、响应性良好的Android应用的关键。 1. **Message Queue(消息队列)的角色** - 每个线程不自动创建Message Loop,需要手动通过Looper类来建立。 - ...
Handler、Looper和MessageQueue是Android异步处理机制中的核心组件,它们共同构建了一个消息传递系统,使得在不同线程间进行数据交换变得可能。下面我们将深入探讨这三个组件的工作原理及其在实际开发中的应用。 ...
在Android操作系统中,MessageQueue是实现线程间通信和异步处理的核心组件。它与Handler、Looper紧密协作,构成了Android消息传递机制的基础。本压缩包文件"android_os_MessageQueue.rar_android"显然关注的是这一...
在Android系统中,MessageQueue和Looper是两个非常关键的组件,它们构成了消息处理机制的核心,尤其是在UI线程中。理解并有效地使用它们对于编写高效、响应迅速的Android应用至关重要。 `Looper`是Android中的一个...
在Android系统中,消息机制是实现线程间通信的关键组件,而`Looper`与`MessageQueue`则是这一机制的核心部分。本文将深入探讨`Looper`的使用及其在管理`MessageQueue`中的作用。 首先,`Looper`是Android系统中一个...
Looper 对象通过 MessageQueue 来存放消息和事件,每个线程只能有一个 Looper 对象,-corresponding to one MessageQueue。 Android 中的 Looper 对象可以通过以下三种方式创建: 1. 系统默认创建:在主线程中,...
通过阅读《android MessageQueue1.doc》、《android MessageQueue2.doc》和《android MessageQueue3.doc》,你可以更深入地了解MessageQueue的实现细节、使用技巧以及常见问题的解决方案,这对于提升Android应用的...
Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理. 简单定义: 1、Message Queue(消息队列): 用来存放通过Handler发布的消息,通常...
4. **Looper**:充当MessageQueue和Handler之间的桥梁角色,负责循环取出MessageQueue中的消息,并交给对应的Handler处理。 #### 四、消息处理流程 1. **创建Handler**:每个需要处理消息的线程都需要一个Handler...
在Android系统中,Message, MessageQueue, Looper, 和 Handler共同构成了一个跨线程通信机制,使得UI线程和其他工作线程之间能安全地交换数据和执行任务,这对于实现复杂的异步操作和保持用户界面的响应性至关重要。...
深入 Android Handler,MessageQueue 与 Looper 关系 Android 消息机制是 Android 程序设计中非常重要的一部分,其中 Handler、MessageQueue 和 Looper 是三个紧密相关的概念。Handler 是 Android 消息机制的上层...
- **MessageQueue的创建**:Looper会创建一个MessageQueue,用于存储各个对象发送的消息,包括用户界面事件和系统事件。 - **定义Handler子类**:开发者可以定义Handler的子类来接收Looper分发的消息。Handler子类...
综上所述,理解并熟练运用Message Queue、Looper和Handler是Android开发中的必备技能,它们构成了Android异步通信的基础框架,确保了UI线程的响应性和安全性。通过合理使用这些机制,开发者可以实现复杂的多线程交互...
Looper,MessageQueue,Handler分析之ActivityThread.java