1.handler的创建
private Handler mHandler = new Handler(){
public void handleMessage(Message msg){
mTextView.setText(""+msg.arg1+"-"+msg.arg2);
};
};
来看Handler的构造函数
/**
* 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);
}
注释里面的意思是针对当前线程创建一个Handler,如果当前线程没有looper(一个专门处理消息队列的循环)的,则抛出异常
2.Looper和Handler的关系
handler的构造函数最终会调用到这里
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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
重点看这个红色部分这段代码就是说你创建的handler里面的成员mLooper指向当前线程的Looper对象.mQueue也是指向当前线程的Looper的mQueue(消息队列)
3.Looper是什么
Looper的主要作用是开启一个无限循环,去消息队列取消息并处理消息,但在开启循环之前要检查你的Looper对象是否已经创建起来
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
/**
* 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();
}
返回一个当前线程关联的Looper对象
sThreadLocal 是个什么东西?
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
注释里面的意思就是如果没有调用prepare()就返回为空,你的应用主线程启动的时候会调用(你不用自己再写这个代码)
Looper.prepare();
这个prepare()做了下面这个事情
/** 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() {
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));
}
ThreadLocal 解释
threadlocal而是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据,更具体的可以百度
从上面代码中可以看出在一个线程里面prepare()只能调用一次,多了会抛出异常.这样就保证一个线程里面只能有一个Looper对象.如果你想要在你的子线程里面创建Looper可以这样做
Thread thread = new Thread(){
@Override
public void run() {
super.run();
//初始化Looper,一定要写在Handler初始化之前
Looper.prepare();
//在子线程内部初始化handler即可,发送消息的代码可在主线程任意地方发送
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//所有的事情处理完成后要退出looper,即终止Looper循环
//这两个方法都可以,有关这两个方法的区别自行寻找答案
handler.getLooper().quit();
handler.getLooper().quitSafely();
}
};
//启动Looper循环,否则Handler无法收到消息
Looper.loop();
}
};
45.消息队列的处理
前面提到的
public static void loop()
里面是这样做的
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
queue.next()
如果取不到新的消息就会线程就会阻塞避免无限
循环导致CPU占用过高具体
如下
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
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) {
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 (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
-----------------
里面也有个无限循环当取不到新的消息之后nextPollTimeoutMillis = -1;
nativePollOnce(ptr, nextPollTimeoutMillis);
1.如果nextPollTimeoutMillis=-1,一直阻塞不会超时。
2.如果nextPollTimeoutMillis=0,不会阻塞,立即返回。
3.如果nextPollTimeoutMillis>0,最长阻塞nextPollTimeoutMillis毫秒(超时),如果期间有程序唤醒会立即返回
当然如果有新的消息队列插入那么就会立即处理新的消息,取消阻塞状态,这些是通过linux系统调用实现的。
--------------------------------------------
5.Handler如何发消息
/**
* Executes the message synchronously if called on the same thread this handler corresponds to,
* or {@link #sendMessage pushes it to the queue} otherwise
*
* @return Returns true if the message was successfully ran or placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
* @hide
*/
public final boolean executeOrSendMessage(Message msg) {
if (mLooper == Looper.myLooper()) {
dispatchMessage(msg);
return true;
}
return sendMessage(msg);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}