總結(jié)
Handler類的主要作用是發(fā)送一個(gè)Message信息到消息隊(duì)列楷拳,根據(jù)持有的Looper決定把Message發(fā)送到那個(gè)線程的消息隊(duì)列趣斤,也可以延時(shí)發(fā)送俩块,在Looper#loop方法中
msg.target.dispatchMessage(msg)
開始分發(fā)結(jié)果。如果不在需要發(fā)送Message消息浓领,先查看一下消息隊(duì)列中是否有此消息玉凯。根據(jù)條件removeMessages。
代碼
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
tv_handler_test_result.setText((String) msg.obj);
break;
}
}
};
private TextView tv_handler_test_result;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_test);
tv_handler_test_result = (TextView) findViewById(R.id.tv_handler_test_result);
Button btn_handler_test_send = (Button) findViewById(R.id.btn_handler_test_send);
btn_handler_test_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message obtain = Message.obtain();
obtain.obj = "來吧兄弟!";
obtain.what = 0;
handler.sendMessage(obtain);
super.run();
}
}.start();
}
});
}
簡單到令人發(fā)指的代碼联贩。點(diǎn)擊button按鈕發(fā)送漫仆,子線程延時(shí)5秒發(fā)送信息。在handler接受到信息泪幌,回顯到textview中盲厌。
handler 如何工作
handler類的描述
/**
* A Handler allows you to send and process {@link Message} and Runnable
* objects associated with a thread's {@link MessageQueue}. Each Handler
* instance is associated with a single thread and that thread's message
* queue. When you create a new Handler, it is bound to the thread /
* message queue of the thread that is creating it -- from that point on,
* it will deliver messages and runnables to that message queue and execute
* them as they come out of the message queue.
*
* <p>There are two main uses for a Handler: (1) to schedule messages and
* runnables to be executed as some point in the future; and (2) to enqueue
* an action to be performed on a different thread than your own.
*
* <p>Scheduling messages is accomplished with the
* {@link #post}, {@link #postAtTime(Runnable, long)},
* {@link #postDelayed}, {@link #sendEmptyMessage},
* {@link #sendMessage}, {@link #sendMessageAtTime}, and
* {@link #sendMessageDelayed} methods. The <em>post</em> versions allow
* you to enqueue Runnable objects to be called by the message queue when
* they are received; the <em>sendMessage</em> versions allow you to enqueue
* a {@link Message} object containing a bundle of data that will be
* processed by the Handler's {@link #handleMessage} method (requiring that
* you implement a subclass of Handler).
*
* <p>When posting or sending to a Handler, you can either
* allow the item to be processed as soon as the message queue is ready
* to do so, or specify a delay before it gets processed or absolute time for
* it to be processed. The latter two allow you to implement timeouts,
* ticks, and other timing-based behavior.
*
* <p>When a
* process is created for your application, its main thread is dedicated to
* running a message queue that takes care of managing the top-level
* application objects (activities, broadcast receivers, etc) and any windows
* they create. You can create your own threads, and communicate back with
* the main application thread through a Handler. This is done by calling
* the same <em>post</em> or <em>sendMessage</em> methods as before, but from
* your new thread. The given Runnable or Message will then be scheduled
* in the Handler's message queue and processed when appropriate.
*/
翻譯:Handler允許你發(fā)送和處理與線程的MessageQueue相關(guān)的Message和Runnable對(duì)象。
每一個(gè)實(shí)例都與單個(gè)線程和該線程的MessageQueue相關(guān)聯(lián)祸泪。
如果創(chuàng)建一個(gè)新的Handler,它 綁定到 正在創(chuàng)建他的線程 的線程/messageQueue吗浩,在這一刻起,handler將分發(fā)Message没隘,或者Runnable懂扼,并發(fā)送到消息隊(duì)列Message Queue。
handler有兩個(gè)主要的作用:
- 在將來的某個(gè)時(shí)間點(diǎn)去調(diào)度Message和Runnable
- 在另一個(gè)線程上去執(zhí)行隊(duì)列
發(fā)送消息是通過下面的一些方法發(fā)送的:
post類型
{@link #post}, {@link #postAtTime(Runnable, long)}, {@link #postDelayed}允許發(fā)送runnable,接收到message調(diào)用在runnable中阀湿。
send類型{@link #sendEmptyMessage}, {@link #sendMessage}, {@link #sendMessageAtTime}, and {@link #sendMessageDelayed}
發(fā)送的是Messge對(duì)象赶熟,回調(diào)在handlerMessage方法中。
當(dāng)正在發(fā)送Handler時(shí)陷嘴,可以選擇立刻發(fā)送消息或者指定延時(shí)時(shí)間在發(fā)送消息映砖。
為應(yīng)用程序創(chuàng)建一個(gè)進(jìn)程時(shí),其主線程將專門運(yùn)行一個(gè)消息隊(duì)列罩旋,負(fù)責(zé)管理頂級(jí)應(yīng)用程序?qū)ο螅ɑ顒?dòng)啊央,廣播接收器等)及其創(chuàng)建的任何窗口。 也可以創(chuàng)建自己的線程涨醋,并通過Handler與主線程進(jìn)行通信瓜饥。 這是通過調(diào)用與之前相同的<em> post </ em>或<em> sendMessage </ em>方法來完成的,但是是從新線程調(diào)用的浴骂。 然后給定的Runnable或Message將在Handler的消息隊(duì)列中進(jìn)行調(diào)度乓土,并在適當(dāng)?shù)臅r(shí)候進(jìn)行處理
默認(rèn)構(gòu)造
/**
* 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);
}
翻譯:默認(rèn)的構(gòu)造,handler和當(dāng)前的線程Looper相關(guān)聯(lián)溯警。
如果這個(gè)線程沒有l(wèi)ooper趣苏,handler不想接受你的線程,并向你拋出個(gè)異常梯轻。
CallBack構(gòu)造
/**
* Constructor associates this handler with the {@link Looper} for the
* current thread and takes a callback interface in which you can handle
* messages.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*
* @param callback The callback interface in which to handle messages, or null.
*/
public Handler(Callback callback) {
this(callback, false);
}
callback自定義回調(diào),可以自己處理message
Looper構(gòu)造
/**
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public Handler(Looper looper) {
this(looper, null, false);
}
使用自己定義的looper 而不是默認(rèn)的looper食磕,looper不能為空
Looper CallBack構(gòu)造
/**
* Use the provided {@link Looper} instead of the default one and take a callback
* interface in which to handle messages.
*
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
*/
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
boolean async 構(gòu)造
/**
* Use the {@link Looper} for the current thread
* and set whether the handler should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
public Handler(boolean async) {
this(null, async);
}
使用當(dāng)前線程的looper,并設(shè)置handler是否應(yīng)該是異步的喳挑。
默認(rèn)是同步的彬伦,除非使用這個(gè)構(gòu)造來創(chuàng)建一個(gè)嚴(yán)格的異步。
異步消息表示不需要遵守同步消息的全局排序的中斷或事件伊诵。 異步消息不受由{@link MessageQueue#enqueueSyncBarrier(long)}引入的同步障礙的限制
CallBack回調(diào)接口
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
結(jié)果回調(diào)接口
返回:ture 表示不需要繼續(xù)處理了
真正調(diào)用的構(gòu)造
使用上面的哪些構(gòu)造都是使用了一些默認(rèn)的參數(shù)单绑。到這里才是開始真正的開始。
這里主要有兩個(gè)構(gòu)造主要看參數(shù)曹宴。
/**
* Use the {@link Looper} for the current thread with the specified callback interface
* and set whether the handler should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
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 that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
這個(gè)構(gòu)造是隱藏的搂橙,當(dāng)loop==null就會(huì)拋出異常。
myLooper()方法 會(huì)返回一個(gè)與當(dāng)前線程相關(guān)聯(lián)的looper對(duì)象笛坦,如果線程沒有和looper相關(guān)聯(lián) 就會(huì)返回null.
/**
* 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();
}
如果不調(diào)用prepare()方法 区转,sThreadLocal.get()會(huì)返回null.
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
FIND_POTENTIAL_LEAKS 默認(rèn)為false,將此標(biāo)志設(shè)置為true以檢測版扩,局部或成員類废离。 這些類可能會(huì)造成泄漏。
/**
* Use the provided {@link Looper} instead of the default one and take a callback
* interface in which to handle messages. Also set whether the handler
* should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
這個(gè)就比較簡單了资厉,使用提供的{@link Looper}而不是默認(rèn)的厅缺,并采用一個(gè)回調(diào)接口來處理消息。 還要設(shè)置處理程序是否應(yīng)該是異步的。
getMessageName
/**
* Returns a string representing the name of the specified message.
* The default implementation will either return the class name of the
* message callback if any, or the hexadecimal representation of the
* message "what" field.
*
* @param message The message whose name is being queried
*/
public String getMessageName(Message message) {
if (message.callback != null) {
return message.callback.getClass().getName();
}
return "0x" + Integer.toHexString(message.what);
}
返回表示指定消息的名稱的字符串湘捎。默認(rèn)實(shí)現(xiàn)將返回消息回調(diào)的類名或消息“what”字段的十六進(jìn)制表示形式诀豁。
/**
* Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
* If you don't want that facility, just call Message.obtain() instead.
*/
public final Message obtainMessage()
{
return Message.obtain(this);
}
獲取Message系列和Message.obtainMessage()效果一樣;其實(shí)就是一樣的。
post系列
- post
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* @param r The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
把自定義的runnable 添加到消息隊(duì)列中窥妇。runnable將運(yùn)行在handler關(guān)聯(lián)的線程上舷胜。
- postAtTime延時(shí)發(fā)送消息
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
發(fā)送延時(shí)消息,與上面的差不多活翩,加入延時(shí)時(shí)間烹骨,如果在深度睡眠中,會(huì)添加延時(shí)時(shí)間材泄。
- postDelayed
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
post系列 無非就是調(diào)用sendMessageDelayed或者sendMessageAtTime沮焕,都是發(fā)送延時(shí)消息。首先來看看getPostMessage(r)這個(gè)方法,下面就是這個(gè)方法的實(shí)現(xiàn)拉宗,首先new出一個(gè)Message的實(shí)例峦树,然后把runnable賦值到Message的回調(diào)中。
也就說明Measage中的Callback其實(shí)就是我們自定義的Runnable,所以使用post系列發(fā)送消息的旦事,Message都有Callback魁巩,而在handler類中,message.callback 其實(shí)就是自己定義的runnable
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
在來看sendMessageDelayed方法姐浮,也是調(diào)用sendMessageAtTime方法谷遂,SystemClock.uptimeMillis() + delayMillis。delayMillis延時(shí)時(shí)間
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
- post系列最終都是調(diào)用這個(gè)方法 sendMessageAtTime
/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* Time spent in deep sleep will add an additional delay to execution.
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
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);
}
首先查看mQueue消息隊(duì)列是否為null卖鲤,最后執(zhí)行enqueueMessage方法肾扰。這里的延遲時(shí)間 你寫個(gè)5000之類的就錯(cuò)了,需要加上SystemClock.uptimeMillis()扫尖。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
把當(dāng)前的handler賦值給Message的target白对,具體有什么用掠廓,咱現(xiàn)在也不知道换怖,但是要有個(gè)印象記住這個(gè)target。mAsynchronous是構(gòu)造的時(shí)候是否需要異步蟀瞧。最后執(zhí)行消息隊(duì)列中的EnqueueMessage方法沉颂。
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
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;
}
接受兩個(gè)參數(shù) 消息 和 時(shí)間,第一步悦污,比較熟悉铸屉,剛才那個(gè)target看見沒,直接已經(jīng)告訴你了 Message必須得有一個(gè)target切端,具體啥用 現(xiàn)在還不知道彻坛。第二部呢從名字上也能分辨 這個(gè)message有沒有正在使用,如果正在使用呢 那就拋異常吧。同步鎖昌屉,然后判斷是否正在退出中钙蒙,mQuitting其實(shí)表示Looper如果Looper正在關(guān)閉中,你不應(yīng)該在去發(fā)送消息了间驮。markInUse表示Message正在處理中躬厌。后面比較復(fù)雜不懂。一會(huì)在看
- isInUse()
/*package*/ static final int FLAG_IN_USE = 1 << 0;
/*package*/ int flags;
/*package*/ boolean isInUse() {
return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
}
- markInUse
/*package*/ void markInUse() {
flags |= FLAG_IN_USE;
}
- sendMessageAtFrontOfQueue 這個(gè)方法會(huì)把消息方在隊(duì)列的最前面
/**
* Enqueue a message at the front of the message queue, to be processed on
* the next iteration of the message loop. You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
* <b>This method is only for use in very special circumstances -- it
* can easily starve the message queue, cause ordering problems, or have
* other unexpected side-effects.</b>
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessageAtFrontOfQueue(Message msg) {
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, 0);
}
把消息放在消息隊(duì)列的最前面竞帽,在消息循環(huán)中的下一次處理扛施,這個(gè)方法很容易出險(xiǎn)問題,比如排序問題和其它未知問題屹篓。
removeMessages 系列
/**
* Remove any pending posts of messages with code 'what' that are in the
* message queue.
*/
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
根據(jù)what移除所有在消息隊(duì)列等待發(fā)送的消息疙渣。
/**
* Remove any pending posts of messages with code 'what' and whose obj is
* 'object' that are in the message queue. If <var>object</var> is null,
* all messages will be removed.
*/
public final void removeMessages(int what, Object object) {
mQueue.removeMessages(this, what, object);
}
跟上一個(gè)方法類似,多了一個(gè)obj堆巧,如果obj為null昌阿,則刪除所有。
/**
* Remove any pending posts of callbacks and sent messages whose
* <var>obj</var> is <var>token</var>. If <var>token</var> is null,
* all callbacks and messages will be removed.
*/
public final void removeCallbacksAndMessages(Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
類似恳邀,如果token為null懦冰,則刪除所有message和callback
hasMessages 系列
/**
* Check if there are any pending posts of messages with code 'what' in
* the message queue.
*/
public final boolean hasMessages(int what) {
return mQueue.hasMessages(this, what, null);
}
/**
* Check if there are any pending posts of messages with code 'what' and
* whose obj is 'object' in the message queue.
*/
public final boolean hasMessages(int what, Object object) {
return mQueue.hasMessages(this, what, object);
}
/**
* Check if there are any pending posts of messages with callback r in
* the message queue.
*
* @hide
*/
public final boolean hasCallbacks(Runnable r) {
return mQueue.hasMessages(this, r, null);
}
校驗(yàn)消息隊(duì)列中,是否有要發(fā)送的runnable或者message
回調(diào)
public interface Callback {
public boolean handleMessage(Message msg);
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
dispatchMessage方法在Looper#loop()中被調(diào)用谣沸,msg就是發(fā)送出來的結(jié)果刷钢,在發(fā)送給handleMessage或者h(yuǎn)andleCallback,這里就看你代碼中使用的是哪一種回調(diào)了乳附。
其它
/**
* Runs the specified task synchronously.
* <p>
* If the current thread is the same as the handler thread, then the runnable
* runs immediately without being enqueued. Otherwise, posts the runnable
* to the handler and waits for it to complete before returning.
* </p><p>
* This method is dangerous! Improper use can result in deadlocks.
* Never call this method while any locks are held or use it in a
* possibly re-entrant manner.
* </p><p>
* This method is occasionally useful in situations where a background thread
* must synchronously await completion of a task that must run on the
* handler's thread. However, this problem is often a symptom of bad design.
* Consider improving the design (if possible) before resorting to this method.
* </p><p>
* One example of where you might want to use this method is when you just
* set up a Handler thread and need to perform some initialization steps on
* it before continuing execution.
* </p><p>
* If timeout occurs then this method returns <code>false</code> but the runnable
* will remain posted on the handler and may already be in progress or
* complete at a later time.
* </p><p>
* When using this method, be sure to use {@link Looper#quitSafely} when
* quitting the looper. Otherwise {@link #runWithScissors} may hang indefinitely.
* (TODO: We should fix this by making MessageQueue aware of blocking runnables.)
* </p>
*
* @param r The Runnable that will be executed synchronously.
* @param timeout The timeout in milliseconds, or 0 to wait indefinitely.
*
* @return Returns true if the Runnable was successfully executed.
* Returns false on failure, usually because the
* looper processing the message queue is exiting.
*
* @hide This method is prone to abuse and should probably not be in the API.
* If we ever do make it part of the API, we might want to rename it to something
* less funny like runUnsafe().
*/
public final boolean runWithScissors(final Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
翻譯:同步運(yùn)行指定的任務(wù)
如果當(dāng)前線程與處理程序線程相同内地,則runnable立即運(yùn)行而不被入隊(duì)。否則赋除,將runnable發(fā)布到處理程序阱缓,并在返回之前等待它完成。這種方法很危險(xiǎn)举农!不正確的使用會(huì)導(dǎo)致死鎖荆针。永遠(yuǎn)不要在保持鎖的時(shí)候調(diào)用這個(gè)方法,或者以可能的方式重新使用它颁糟。
在后臺(tái)線程必須同步等待完成必須在處理程序線程上運(yùn)行的任務(wù)的情況下航背,此方法偶爾很有用。但是棱貌,這個(gè)問題往往是設(shè)計(jì)不好的一個(gè)癥狀玖媚。考慮在采用這種方法之前改進(jìn)設(shè)計(jì)(如果可能的話)
您只需設(shè)置一個(gè)Handler線程婚脱,并在繼續(xù)執(zhí)行之前需要對(duì)其執(zhí)行一些初始化步驟
如果發(fā)生超時(shí)今魔,則此方法返回<code> false </ code>勺像,但runnable將保留在處理程序上,并且可能已在進(jìn)行或稍后完成错森。
private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run();
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
if (!handler.post(this)) {
return false;
}
synchronized (this) {
if (timeout > 0) {
final long expirationTime = SystemClock.uptimeMillis() + timeout;
while (!mDone) {
long delay = expirationTime - SystemClock.uptimeMillis();
if (delay <= 0) {
return false; // timeout
}
try {
wait(delay);
} catch (InterruptedException ex) {
}
}
} else {
while (!mDone) {
try {
wait();
} catch (InterruptedException ex) {
}
}
}
}
return true;
}
}
runWithScissors保留