Android Handler移除Message詳解及實(shí)例代碼
Android Handler移除Message詳解
問(wèn)題:
1.removeMessage(what)函數(shù)是否只能移除對(duì)應(yīng)what值的Message?
2.對(duì)于Delayed發(fā)送的Message,能否提前remove?
代碼測(cè)試:
package javine.k.testhandler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class TestHandlerActivity extends Activity implements OnClickListener {
private Button startBtn;
private Button endBtn;
public Handler threadHandler; //子線程Handler
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
threadHandler.sendEmptyMessageDelayed(1, 2000);
Log.d("info", "handle main-thread message...");
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startBtn = (Button) findViewById(R.id.startButton);
endBtn = (Button) findViewById(R.id.endButton);
startBtn.setOnClickListener(this);
endBtn.setOnClickListener(this);
new Thread(new Runnable() {
@Override
public void run() {
HandlerThread handlerThread = new HandlerThread("handler");
handlerThread.start();
threadHandler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
//mHandler.sendEmptyMessageDelayed(0, 2000);<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="white-space:pre"></span><pre name="code" class="java"><span style="white-space:pre"> </span>mHandler.sendEmptyMessageDelayed(1, 2000);
Log.d("info", "handle sub-thread message...");}};}}).start();}@Overridepublic void onClick(View v)
{// TODO Auto-generated method stubswitch (v.getId()) {case R.id.startButton:
//開(kāi)始發(fā)送消息mHandler.sendEmptyMessage(1);break;case R.id.endButton:
//移除主線程Handler的消息mHandler.removeMessages(1);break;default:break;}}}
測(cè)試結(jié)果:
1. removeMassage(1)無(wú)法移除what=0的Message。
2. 在子線程中執(zhí)行完
<span></span><pre name="code" class="java"><span style="white-space:pre"> </span>mHandler.sendEmptyMessageDelayed(1, 2000);
Log.d("info", "handle sub-thread message...");
之后,即可通過(guò)removeMesage(1)來(lái)移除消息,mHandler將不能接收到該條消息。
源碼分析:
1.Android如何移除一條Message?
查看源碼可知,Handler.removeMessage(int what)內(nèi)部調(diào)用MessageQueue.removeMessage(this, what, null)
查看MessageQueue的removeMessage方法如下:
void removeMessages(Handler h, int what, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycle();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycle();
p.next = nn;
continue;
}
}
p = n;
}
}
}
篩選要移除的Message的條件是:target(handler),what,object
該函數(shù)分兩步來(lái)移除Message:
1).移除在前端的符合條件的Message
2).移除后面的符合條件的Message
2.為何延遲發(fā)送的Message在延遲時(shí)間到達(dá)之前就可以被移除?
Handler.sendEmptyMessageDelayed() ---調(diào)用---> sendMessageAtTime() -----調(diào)用---> enqueueMessage() ----調(diào)用MessageQueue.enqueueMessage()
實(shí)際進(jìn)行處理的就是MessageQueue,源碼如下:
boolean enqueueMessage(Message msg, long when) {
if (msg.isInUse()) {
throw new AndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null) {
throw new AndroidRuntimeException("Message must have a target.");
}
synchronized (this) {
if (mQuitting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
}
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;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
由上可知:MessageQueue會(huì)對(duì)需要延遲發(fā)送的Message排序,按照需要延遲的時(shí)間長(zhǎng)短(when)。
即,雖然是延遲發(fā)送的消息,其實(shí)當(dāng)你調(diào)用發(fā)送函數(shù)之后,Message就已經(jīng)被添加到MessageQueue中去了。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android簽名文件轉(zhuǎn)化為pk8和pem的實(shí)現(xiàn)
這篇文章主要介紹了Android簽名文件轉(zhuǎn)化為pk8和pem的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
Android viewpager在最后一頁(yè)滑動(dòng)之后跳轉(zhuǎn)到主頁(yè)面的實(shí)例代碼
這篇文章主要介紹了Android viewpager在最后一頁(yè)滑動(dòng)之后跳轉(zhuǎn)到主頁(yè)面的實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-08-08
Android開(kāi)發(fā)之splash界面下詳解及實(shí)例
這篇文章主要介紹了 Android開(kāi)發(fā)之splash界面下詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03
Android 圖文詳解Binder進(jìn)程通信底層原理
Android系統(tǒng)中,多進(jìn)程間的通信都是依賴于底層Binder IPC機(jī)制,Binder機(jī)制是一種RPC方案。例如:當(dāng)進(jìn)程A中的Activity與進(jìn)程B中的Service通信時(shí),就使用了binder機(jī)制2021-10-10
Android實(shí)現(xiàn)帶附件的郵件發(fā)送功能
這篇文章主要介紹了Android實(shí)現(xiàn)帶附件的郵件發(fā)送功能的相關(guān)資料,android發(fā)送郵件有兩種方式,本文重點(diǎn)介紹基于JMail實(shí)現(xiàn)郵件發(fā)送功能,感興趣的小伙伴們可以參考一下2016-01-01
Android實(shí)現(xiàn)獲取短信驗(yàn)證碼并自動(dòng)填寫功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)獲取短信驗(yàn)證碼并自動(dòng)填寫功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Android存儲(chǔ)訪問(wèn)框架的使用小結(jié)
這篇文章主要介紹了Android存儲(chǔ)訪問(wèn)框架的使用,存儲(chǔ)訪問(wèn)框架API和MediaStore?API的差異,在于存儲(chǔ)訪問(wèn)框架API,是基于系統(tǒng)文件選擇框的,用戶選擇了文件,那么相當(dāng)于授權(quán)了,?可以訪問(wèn)所有類型的文件,需要的朋友可以參考下2022-01-01

