Looper 对象 使用 Handler 的构造方法 new Handler(Looper looper) 来创建Handler
这样即使在子线程也能new 出主线程的Handler
AsyncTask 的新代码就是使用的这种方式
老代码是直接在 主线程 new Handler()
一、Message
1. 用于携带数据
------------------------
arg1 arg2
两个整型值
obj Object类型,
可以传送任意对象到接受者中
what int 类型
用户自定义常量值 用于识别消息类型
target Handler 对象
用于存放 该msg 是由哪个 Handler 发送的 用于以后对消息的分发
2. 用于提高性能维护消息池
----------------------------
next Message 类型
使用链表结构存储消息
static sPool Message
全局的 消息池 sPool 是链表头
池中的数据以单项链表的形式储存
android 推荐使用Message.obtain() 或 Message.obtainMessage()
从消息池中获取对象
消息池链表最大长度 MAX_POOL_SIZE 50
public void recycle() 回收不实用的Message
在 Looper 的死循环中进行回收
Message.obtain() 获取一个可以使用的Message
源码:
public final class Message implements Parcelable {
/**
* User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has its own name-space
* for message codes, so you do not need to worry about yours conflicting
* with other handlers.
*/
public int what;
/**
* An arbitrary object to send to the recipient. When using
* {@link Messenger} to send the message across processes this can only
* be non-null if it contains a Parcelable of a framework class (not one
* implemented by the application). For other data transfer use
* {@link #setData}.
*
* <p>Note that Parcelable objects here are not supported prior to
* the {@link android.os.Build.VERSION_CODES#FROYO} release.
*/
public Object obj;
// sometimes we store linked lists of these things
/*package*/ Message next;
private static final Object sPoolSync = new Object(); // 静态全局变量 多线程同步使用的
private static Message sPool; // 静态全局变量 Message 链表池,
private static int sPoolSize = 0; // 消息池的实时大小
private static final int MAX_POOL_SIZE = 50; // 消息池最大容量
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
/**
* Return a Message instance to the global pool.
* <p>
* You MUST NOT touch the Message after calling this function because it has
* effectively been freed. It is an error to recycle a message that is currently
* enqueued or that is in the process of being delivered to a Handler.
* </p>
*/
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
}
二、MessageQueue
消息队列 维护用于存放消息的数据结构
一个线程 有且仅有一个 MessageQueue
MessageQueue对象不需要我们自己创建,
而是有Looper对象对其进行管理,
有消息入队,如果消息有延迟时间就排到队列后,
如果没有则排到队列前面,
排好对后等待Looperde loop方法从消息队列中取消息
源码:
/**
* Low-level class holding the list of messages to be dispatched by a
* {@link Looper}. Messages are not added directly to a MessageQueue,
* but rather through {@link Handler} objects associated with the Looper.
*
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
public final class MessageQueue {
private native static long nativeInit();
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
msg.markInUse();
msg.when = when;
Message p = mMessages;
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
return true;
}
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
mMessages = msg.next;
msg.next = null;
msg.markInUse();
return msg;
}
}
}
}
}
三、Looper
MessageQueue对象不需要我们自己创建,
而是有Looper对象对其进行管理,
在android 中除了在主线程有默认的Looper对象
在 ActivityThread.java 中的 main 方法中
主线程 Looper.prepareMainLooper(); 准备Looper
子线程 Looper.prepare(); 准备Looper
1.为当前线程new Looper 对象
2. 为该Looper new 出对应的 MessageQueue
ThreadLocal:线程本地变量,在哪个线程set的值,只能在那个线程获取出来
功能:可以让每一个线程都有一个属于自己独有的值
所有的线程都会共享一个ThreadLocal 对象,每一个线程访问它都
会得到不同的值,并且修改一个线程的值不会影响别的线程的值,
可以存放 null 值
执行Looper.loop(); 进行死循环处理消息
源码:
public final class Looper {
// ThreadLocal 线程本地变量。 在A线程保存的数据,只能在A线程取出来。
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
final MessageQueue mQueue;
final Thread mThread;
/** 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()}.
*/
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));
}
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
try {
msg.target.dispatchMessage(msg); // target 就是Handler, 分发消息, 看一看出 发出去的Message的target 不可能为null
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.recycleUnchecked(); // 回收 Message
}
}
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
子线程使用方法
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
//将当前线程初始化为一个Looper线程
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
四、Handler
mQueue MessageQueue
mLooper Looper
在new 的时候 会获取本线程的 消息队列
和 Looper 对象
方便将消息 入队 enqueue
handler.sendMessage(msg);
将msg 添加到handler 所在线程的消息队列中 MessageQueue
等待loop 方法将消息队列中的msg 拿到
然后执行msg.target.dispatchMessage(msg);
源码:
dispatchMessage(Message msg) {
this.handleMessage(msg);
}
public class Handler {
/**
* Use the {@link Looper} for the current thread with the specified callback interface
* and set whether the handler should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @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;
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
/**
* 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);
}
}
/**
* Pushes a message onto the end of the message queue after all pending messages
* before the current time. It will be received in {@link #handleMessage},
* in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
/**
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* Time spent in deep sleep will add an additional delay to execution.
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
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);
}
}
有且只有一个 Looper MessageQueue 对象
但是Handler 对象可以有多个。
每一个Handler 对象中都会保存相同的
Looper MessageQueue对象 因为这些Handler都属于同一个线程
在一个App中:
Message 消息池只存在一个
1、在任意线程中 Handler对象通过obtainMessage方法从消息池中获取消息,通过sendMessage方法将消息发送到消息队列中;
2、Handler 通过 handler.sendMessage(msg); 调用 MessageQueue的enqueueMessage消息入队方法
3、Looper.loop() 方法死循环 不断从MessageQueue中取消息(Message) 调用Message.target.dispatchMessage(msg)
调用Handler的 handleMessage方法在本线程中执行