一直對handler似懂非懂,此次看了別的文章加上本身的理解,終於明白Handler究竟是如何實現線程間的通訊了.你們共同探討研究.
首先得明白,一個線程只有一個Looper和MessageQueue.調用本線程的Handler只能發送Message到本線程的MessageQueue.那怎麼區分Handler是哪一個線程的呢,是經過Handler對象中的Looper對象.而後本線程Looper對象loop(),不斷從MessageQueue取消息.bash
//內存泄漏的問題請先忽略
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
...
}
}
};
複製代碼
直接新建一個Handler,它是主線程的.答案在源碼.看下面.ide
//Handler源碼片斷
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
...
mLooper = Looper.myLooper(); //注意這句
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
...
複製代碼
mLooper = Looper.myLooper(); 這句代碼獲取的是主線程的Looper,而它在ActivityThread中已經初始化過了,這裏很少說.oop
private void childThreadSendMessageToMain() {
new Thread(){
@Override
public void run() {
super.run();
Message message = handler.obtainMessage();
message.what = mess_thread1;
message.obj = "我是子線程1發來的消息";
handler.sendMessage(message); //注意這句
}
}.start();
}
複製代碼
handler.sendMessage(message); 這裏的handler是咱們上面在主線程初始化的,是主線程的Handler,這樣在主線程的handleMessage()中就能夠收到子線程發來的Messageui
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
//注意這裏
case mess_thread1:
Log.d(TAG, "handleMessage: 接收到來自mess_thread1的消息");
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
...
}
}
複製代碼
D/ScrollingActivity: handleMessage: 接收到來自mess_thread1的消息
D/ScrollingActivity: handleMessage: msg.obj=我是子線程1發來的消息
複製代碼
這裏有個問題,當我在主線程使用子線程Handler時,子線程的Handler沒有初始化好怎麼辦?咱們這樣解決:
首先: 子線程裏初始化Handler
再次: 子線程發送給主線程消息: 子線程的Handler準備好了
再次: 主線程使用子線程的Handler發送消息
最後: 子線程接收並處理主線程發送過來的消息spa
private class ChildHandler extends Handler{
//參數爲looper,到時候傳入一個子線程的looper,這個handler就成了子線程的了
private ChildHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
...
}
}
}
複製代碼
private void initChildHandler(){
new Thread(){
@Override
public void run() {
Looper.prepare();
childThreadHandler = new ChildHandler(Looper.myLooper());
Message message = handler.obtainMessage();
message.what = child_handler_ok;
message.obj = "子線程handler準備好了";
handler.sendMessage(message);
Looper.loop();
}
}.start();
}
複製代碼
//接收處理子線程handler準備好的消息
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case child_handler_ok:
Log.d(TAG, "handleMessage: 接收到子線程消息");
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
sendMessageToChildThread();
break;
}
}
};
複製代碼
//使用子線程handler發送消息到子線程
private void sendMessageToChildThread() {
Message message = childThreadHandler.obtainMessage();
message.what = mess_mainThread;
message.obj = "我是主線程,已收到子線程handler準備好的消息";
childThreadHandler.sendMessage(message);
}
複製代碼
private class ChildHandler extends Handler{
private ChildHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case mess_mainThread:
Log.d(TAG, "handleMessage: mess_mainThread");
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
...
break;
...
}
}
}
複製代碼
handleMessage: child_handler_ok
handleMessage: msg.obj=子線程handler準備好了
handleMessage: mess_mainThread
handleMessage: msg.obj=我是主線程,已收到子線程handler準備好的消息
複製代碼
//在子線程2中使用子線程1的handler發送消息,實現了子線程之間的通訊
private void initChild2Thread() {
new Thread(){
@Override
public void run() {
Message message = childThreadHandler.obtainMessage();
message.what = child2_thread;
message.obj = "我是另外一個子線程發送的消息";
childThreadHandler.sendMessage(message);
}
}.start();
}
複製代碼
//這裏說明一下,因爲new的時候咱們傳入了子線程1的looper,因此這個handler屬於子線程1
private class ChildHandler extends Handler{
private ChildHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
...
case child2_thread:
Log.d(TAG, "handleMessage: child2_thread" );
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
break;
}
}
}
複製代碼
D/ScrollingActivity: handleMessage: child2_thread
D/ScrollingActivity: handleMessage: msg.obj=我是另外一個子線程發送的消息
複製代碼
想給哪一個線程發消息,就使用目標線程的Handler對象調用sendMessage(message).
而區別Handler是哪一個線程的,就是Handler持有哪一個線程的Looper.線程