handler源碼分析之Handler類

總結(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è)主要的作用:

  1. 在將來的某個(gè)時(shí)間點(diǎn)去調(diào)度Message和Runnable
  2. 在另一個(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保留

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咏删,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子问词,更是在濱河造成了極大的恐慌督函,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件激挪,死亡現(xiàn)場離奇詭異辰狡,居然都是意外死亡炊邦,警方通過查閱死者的電腦和手機(jī)焊切,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門黎侈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘟栖,“玉大人,你說我怎么就攤上這事艇抠≡姹В” “怎么了佩厚?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵豺瘤,是天一觀的道長吆倦。 經(jīng)常有香客問我,道長坐求,這世上最難降的妖魔是什么蚕泽? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮桥嗤,結(jié)果婚禮上须妻,老公的妹妹穿的比我還像新娘。我一直安慰自己泛领,他們只是感情好荒吏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渊鞋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪篓像。 梳的紋絲不亂的頭發(fā)上动知,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天摊崭,我揣著相機(jī)與錄音,去河邊找鬼杰赛。 笑死呢簸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的乏屯。 我是一名探鬼主播根时,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辰晕!你這毒婦竟也來了蛤迎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤含友,失蹤者是張志新(化名)和其女友劉穎替裆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窘问,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辆童,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惠赫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胸遇。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖汉形,靈堂內(nèi)的尸體忽然破棺而出纸镊,到底是詐尸還是另有隱情,我是刑警寧澤概疆,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布逗威,位于F島的核電站,受9級(jí)特大地震影響岔冀,放射性物質(zhì)發(fā)生泄漏凯旭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一使套、第九天 我趴在偏房一處隱蔽的房頂上張望罐呼。 院中可真熱鬧,春花似錦侦高、人聲如沸嫉柴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽计螺。三九已至夯尽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間登馒,已是汗流浹背匙握。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陈轿,地道東北人圈纺。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像麦射,于是被迫代替她去往敵國和親赠堵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容