目录
一. Handler的主要作用
Handler的主要作用:在子线程中发送消息, 在主线程中更新UI。
二. Handler的基本使用
1. Handler.sendMessage(msg)
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTextView.setText(msg.obj + ""); //更新UI
}
};
//子线程发送消息
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.obj = "6666";
mHandler.sendMessage(message);
}).start();
2. Handler.post(msg)
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler();
//子线程发送消息
new Thread(new Runnable() {
@Override
public void run() {
mHandler.post(new Runnable() { //切换到主线程更新UI
@Override
public void run() {
mTextView.setText("123456");
}
});
}).start();
三. Handler的运行机制
1. Handler.sendMessage(msg)做了些什么?
Handler.java里面的方法(部分关键代码):
sendMessage()
→sendMessageDelayed()
→sendMessageAtTime()
→enqueueMessage
;
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;
...
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
...
return queue.enqueueMessage(msg, uptimeMillis);
}
从上面来看,Handler最终调用了MessageQueue.enqueueMessage()
注意:
msg.target = this;
,msg.target
表示当前对象Handler, 后面Looper.loop()
用到
MessageQueue.enqueueMessage()
boolean enqueueMessage(Message msg, long when) {
{
...
synchronized (this) {
...
msg.when = when;
Message p = mMessages;
boolean needWake;
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;
}
...
}
return true;
}
}
从代码中慢慢分析,我们可以得出结论:其实MessageQueue.enqueueMessage()
方法就是把传进来的Message
消息对象,按照时间顺序、队列的结构 保存起来。
在这里,我们并没有看到Handler.handleMessage()
方法的执行,继续往下看。
2. 从ActivityThread.main()分析
我们就不慢慢从问题引进来了,直奔主题。
public static void main(String[] args) {
Looper.prepareMainLooper(); //初始化
Looper.loop();
}
2.1 Looper.prepareMainLooper()
prepareMainLooper()→prepare()
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) { //如果进行第二次初始化,则报异常
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper(); //赋值
}
}
//有且只有一个ThreadLocal对象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
//进入ThreadLocal源码里set()和get()可以看出,每个线程只保存一个Looper对象
//所以每个线程只能调用一次prepare(),否则会抛异常
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//ThreadLocal保存Looper对象
sThreadLocal.set(new Looper(quitAllowed));
}
注意:prepare()方法 这里有2个关键点:
- sThreadLocal.set() 和 get()方法
- Looper.java构造方法new Looper().
1.ThreadLocal.java 的set()和get()
public T get() {
// Optimized for the fast path.
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
Object[] table = values.table;
int index = hash & values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1];
}
} else {
values = initializeValues(currentThread);
}
return (T) values.getAfterMiss(this);
}
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}
set()
:给当前线程赋值一个:Loop对象
get()
:获取当前线程的Loop对象
2. Looper.java构造方法
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
主要初始化消息队列MessageQueue
,即:一个Loop
有一个MessageQueue
消息队列对象
总结:Looper.prepareMainLooper() 主要作用:
- 初始化
Looper.sThreadLocal.set(new Looper(quitAllowed))
- 初始化
MessageQueue
对象,new Loop()
对应一个MessageQueue
对象
2.2 Looper.loop();
下面是部分的关键代码
public static void loop() {
{
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
for (;;) {
Message msg = queue.next(); // might block
...
msg.target.dispatchMessage(msg);
...
msg.recycle();
}
}
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
代码里面都有注释,最核心代码是msg.target.dispatchMessage(msg)
,msg.target
就是当前的Handler
对象,
接下来我们来看Handler.dispatchMessage()
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这里就执行了handleMessage()
方法
2.3 资源回收处理 msg.recycle()
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
public void recycle() {
clearForRecycle();
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
结论:Msg 对象范围0到50个
最后图解,如下图:
代码分析基于kk