我們常常使用Handler來更新UI,但是很多同學(xué)對Handler的sendMessage和post的區(qū)別不是很了解艺骂,我們先看使用方式的區(qū)別:
sendMessage的用法:
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
//實例化Handler,重寫回調(diào)方法
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0) {
/*sendMessage方法更新UI的操作必須在handler的handleMessage回調(diào)中完成*/
mTextView.setText(new_str);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
new_str = "sendMessage更新UI";
/*sendMessage方法解決UI更新發(fā)送消息給handler(主線程中的handler)*/
mHandler.sendEmptyMessage(0);
}
}).start();
}
post的用法:
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
//實例化Handler
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//這里調(diào)用了post方法,和sendMessage一樣達到了更新UI的目的
mHandler.post(new Runnable() {
@Override
public void run() {
mTextView.setText(new_str);
}
});
}
}).start();
}
上面的兩種用法都是很常見的(這里未考慮內(nèi)存泄漏嗅骄,重點只關(guān)注Handler的使用)箱玷,使用這兩種方法都能夠?qū)崿F(xiàn)UI的更新值桩,那么post和sendMessage有什么區(qū)別呢丽旅,我們要跟蹤源碼來看看post到底做了什么。
handler中post的源碼:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
//獲得了message實例懒浮,將r賦給callback,接下來還是和sendMessage一致的操作飘弧,進入sendMessageDelayed
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
最終還是到sendMessageAtTime這個方法里面
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);
}
所以可以知道,handler.post和handler.sendMessage本質(zhì)上是沒有區(qū)別的砚著,都是發(fā)送一個消息到消息隊列中次伶,只不過post使用方式更簡單。
在handler的出隊列方式中稽穆,可以看到如何進入不同的回調(diào)
消息出隊列源碼
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
//如果是post,callback不為空冠王,直接進入handleCallback
if (msg.callback != null) {
handleCallback(msg);
} else {
//如果是sendMessage,且創(chuàng)建handler時沒有傳入callback,則callback為空,直接進入handleMessage舌镶,也就是我們自己復(fù)寫的處理Message的方法
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
//直接run并不會啟動新線程柱彻,所以這就是post的runnable里面可以直接更新UI的原因
private static void handleCallback(Message message) {
message.callback.run();
}