android消息机制

消息机制:
Android的应用程序是通过消息机制来驱动的,深入理解Android应用程序的消息机制就显得尤为重要,这个消息处理机制主要是围绕消息队列来实现的。

在Android应用程序中,可以在一个线程启动时在内部创建一个消息队列,然后再进入到一个无限循环的模式之中,不断地检查这个消息队列是否有新的消息需要进行处理。如果需要处理,那么该线程就会从这个消息队列中取出消息从而进行处理,如果没有消息需要处理,则线程处于等待状态。

1Android通过Looper、Handler来实现消息循环机制。Android的消息循环是针对线程的,每个线程都可以有自己的消息队列和消息循环。

1.1Looper

Looper负责管理消息队列和消息循环,通过Looper.myLooper()得到当前线程的Looper对象,通过Looper.getMainLooper()得到当前进程的主线程的Looper对象。
Android的消息队列和消息循环都是针对具体线程的,一个线程可以存在一个消息队列和消息循环;
特定线程的消息只能分发给本线程,不能跨线程和跨进程通讯。
但是创建的工作线程默认是没有消息队列和消息循环的,如果想让工作线程具有消息队列和消息循环,就需要在线程中先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环:
Activity是一个UI线程,运行在主线程中,Android系统会在Activity启动时为其创建一个消息队列和消息循环。

//工作线程创建自己的消息队列和消息循环
class WorkThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // 处理收到的消息
            }
        };

        Looper.loop();
    }
}

1.2handler

Handler的作用是把消息加入特定的Looper所管理的消息队列中,并分发和处理该消息队列中的消息。构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper对象创建

一个Activity中可以创建出多个工作线程,如果这些线程把他们消息放入Activity主线程的消息队列中,那么消息就会在主线程中处理了。因为主线程一般负责视图组件的更新操作,对于不是线程安全的视图组件来说,这种方式能够很好的实现视图的更新。

那么,子线程如何把消息放入主线程的消息队列中呢?只要Handler对象以主线程的Looper创建,那么当调用Handler的sendMessage方法,系统就会把消息主线程的消息队列,并且将会在调用handleMessage方法时处理主线程消息队列中的消息。

2.ThreadLocal的理解

2.1总结:

1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。

实例一:

public class ThreadLocalTest {

    // 创建一个Integer型的线程本地变量
    public static final ThreadLocal local = new ThreadLocal() {
        @Override
        protected Integer initialValue() {
            return 0;// 初始值都是0,每个线程获得一个副本
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[5];
        for (int j = 0; j < 5; j++) {
            threads[j] = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 获取当前线程的本地变量,然后累加5次
                    int num = local.get();
                    for (int i = 0; i < 5; i++) {
                        num++;
                    }
                    // 重新设置累加后的本地变量
                    local.set(num);
                    System.out.println(Thread.currentThread().getName() + " : "
                            + local.get());

                }
            }, "Thread-" + j);
        }

        for (Thread thread : threads) {
            thread.start();
        }
    }
}
运行结果可以看出每个线程相互独立

实例二:初始值是一个引用,每个线程都拷贝了这个引用,但是这些引用指向了同一个对象,所以运行结果不是独立的

public class ThreadLocalTest {
    private static Index num = new Index();
    // 创建一个Index类型的本地变量
    private static ThreadLocal local = new ThreadLocal() {
        @Override
        protected Index initialValue() {
            return num;
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[5];
        for (int j = 0; j < 5; j++) {
            threads[j] = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 取出当前线程的本地变量,并累加1000次
                    Index index = local.get();
                    for (int i = 0; i < 1000; i++) {
                        index.increase();
                    }
                    System.out.println(Thread.currentThread().getName() + " : "
                            + index.num);

                }
            }, "Thread-" + j);
        }
        for (Thread thread : threads) {
            thread.start();
        }
    }

    static class Index {
        int num;

        public void increase() {
            num++;
        }
    }
}

2.1ThreadLocal的源码分析

ThreadLocal有一个内部类ThreadLocalMap,这个类的实现占了整个ThreadLocal类源码的一多半。这个ThreadLocalMap的作用非常关键,它就是线程真正保存线程自己本地变量的容器。每一个线程都有自己的单独的一个ThreadLocalMap实例,其所有的本地变量都会保存到这一个map中。

Thread对象都有一个ThreadLocalMap类型的属性threadLocals,这个属性是专门用于保存自己所有的线程本地变量的

public T get() {
        //获取当前执行线程
        Thread t = Thread.currentThread();
        //取得当前线程的ThreadLocalMap实例
        ThreadLocalMap map = getMap(t);
        //如果map不为空,说明该线程已经有了一个ThreadLocalMap实例
        if (map != null) {
            //map中保存线程的所有的线程本地变量,我们要去查找当前线程本地变量
            ThreadLocalMap.Entry e = map.getEntry(this);
            //如果当前线程本地变量存在这个map中,则返回其对应的值
            if (e != null)
                return (T)e.value;
        }
        //如果map不存在或者map中不存在当前线程本地变量,返回初始值
        return setInitialValue();
    }
//直接返回线程对象的threadLocals属性
ThreadLocalMap getMap(Thread t)
 {
     return t.threadLocals;
 }
private T setInitialValue() {
        //获取初始化值,initialValue 就是我们之前覆盖的方法
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //如果map不为空,将初始化值放入到当前线程的ThreadLocalMap对象中
        if (map != null)
            map.set(this, value);
        else
            //当前线程第一次使用本地线程变量,需要对map进行初始化工作
            createMap(t, value);
        //返回初始化值
        return value;
    }
public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);

        if (map != null)
            map.set(this, value);
        //说明线程第一次使用线程本地变量(注意这里的第一次含义)
        else
            createMap(t, value);
    }
public void remove() {
         //获取当前线程的ThreadLocalMap对象
         ThreadLocalMap m = getMap(Thread.currentThread());
         //如果map不为空,则删除该本地变量的值
         if (m != null)
             m.remove(this);
     }

2.2ThreadLocal可能发生的内存泄露问题

http://www.cnblogs.com/onlywujun/p/3524675.html
http://blog.csdn.net/sunxianghuang/article/details/51965621
http://ju.outofmemory.cn/entry/64568

3Looper

3.1prepare方法

new一个Looper对象并放到sThreadLocal中,也就是放到当前Thread的threadLocalMap对象中

    static final ThreadLocal sThreadLocal = new ThreadLocal();
    ...
    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {//一个thread只能创建一个looper对象
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

prepareMainLooper方法由系统调用

    /**
     * Initialize the current thread as a looper, marking it as an
     * application's main looper. The main looper for your application
     * is created by the Android environment, so you should never need
     * to call this function yourself.  See also: {@link #prepare()}
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

3.2Looper的构造方法

创建了一个新的消息队列mQueue,并且获取了当前线程的对象

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

3.3Looper.loop方法

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();//获取当前线程的looper对象
    }
    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
        final Looper me = myLooper();//获取当前线程的looper对象
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;//将mQueue赋值给queue 

        for (;;) {
            Message msg = queue.next(); // might block从消息队列中取出消息
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            } 
            。。。。。。
            msg.target.dispatchMessage(msg);//handler分发消息(这里的target是Handler实例对象)
            。。。。。
            msg.recycleUnchecked();//执行消息的回收工作,将消息存入回收的消息池当中。
        }
    }

4.Message的实现

4.1Message对象的获取

在创建一个Message对象时,有两种方式:一种是new Message(),另外一种是Message.obtain()方法。虽然消息的构造函数是公共的,但最好的方法是调用Message.obtain()或Handler.obtainMessage()方法,从对象池中获取。(对象池中维护的是一个Message链表)

public static Message obtain() {
       synchronized (sPoolSync) {
           if (sPool != null) {
               Message m = sPool;//sPool是链表的头元素
               sPool = m.next;
               m.next = null;
               m.flags = 0; // clear in-use flag
               sPoolSize--;
               return m;
           }
       }
       return new Message();//如果对象池为空就new一个Message对象
    }

4.2Message对象的回收

    /**  
     * 

对一个正在添加到消息队列或者正在被发送到handler的msg对象不能调用这个方法,调用recycle方 * 法后不能在去使用这个msg对象 */ public void recycle() { if (isInUse()) {//判断是否在用 if (gCheckRecycle) { throw new IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked();//回收 } boolean isInUse() { return ((flags & FLAG_IN_USE) == FLAG_IN_USE); } /** * Recycles a Message that may be in-use. * Used internally by the MessageQueue and Looper when disposing of queued Messages. */ void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. //在回收过程中,依然认为该message在使用,所以flag标志为1,但是其它的属性值都赋值为初始值 flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }

5.MessageQueue消息队列

内部维护的数据结构是一个单链表而不是队列

5.1插入消息

在Handler所有发送消息的方法最终都会调用enqueueMessage()方法,而在调用消息队列的enqueueMessage()之前会先对Message的target赋值为当前发送消息的Handler对象。在插入的消息中没有携带Handler对象的,则不会插入到消息队列中。如果这个消息正在使用中,那么也不会重复插入到该消息队列中。

MessageQueue中有一个比较重要的成员变量mMessages,这个变量表示当前线程需要处理的消息。将mMessages赋值给变量p,条件p == null || when == 0 || when < p.when表达了三种情况,第一种:当前消息队列没有需要处理的消息;第二种:插入处理消息的时间为0;第三种:插入的消息处理的时间小于当前需要处理消息的处理时间。这三种情况都是需要优先将该插入的消息插入到单链表的首部。该插入的消息的next值为当前需要处理的消息,next值可能为null,不为null的时候则是一个单链表,插入的消息会加入到该链表中去。第四种情况:插入的消息的处理时间大于等于当前需要处理的消息的处理时间,那么插入的消息还没那么快需要处理,因而需要插入到链表中的合适位置,这个链表是按照处理时间从小到大的顺序来排列的。后续else中代码主要是将插入的消息插入到指定位置的算法处理,关于消息的插入实现原理基本就是这样。

    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;
    }

5.2next方法

Looper.loop中会调用这个方法从消息队列中获取Msg对象

    Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }

                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }

                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;

            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

6.Handler

6.1发送消息

Handler的工作主要是发送消息和处理消息,前面已经简要说明了消息是如何发送的。这里再详细分析一下,Handler发送消息的方式有很多种,但是最终都是通过调用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);
    }
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;//将Handler与Message相关联
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);//调用queue的enqueueMessage方法将消息入队
    }

6.2分发处理消息

Looper.loop方法调用queue的next方法之后会调用handler的dispatchMessage方法去分发消息,分发消息中会调用handleMessage方法

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

消息的处理受到handler的创建方式和msg的插入方式影响

6.2.1使用post发消息

发送一个Runnabe对象,该对象会通过getPostMessage()方法与Message关联,那么在分发消息时就会执行handleCallback()方法

6.2.2

如果使用的是在创建Handler对象时传入了CallBack回调,那么会执行mCallback.handleMessage()方法。

6.2.3

以上两个都不是,走handleMessage方法

7.总体流程

Android的消息处理机制主要是围绕消息队列来实现的,在一个线程中通过调用Looper.prepare()方法来创建消息队列和Looper对象,在该线程中创建能发送和处理消息的Handler对象,而Handler通过Looper对象来关联消息队列。Handler发送消息到与之关联的消息队列(MessageQueue对象),通过MessageQueue对象的enqueueMessage的方法将消息插入到消息队列当中。而在发送的消息中,又将Handler与消息建立对应关系,每一个消息中的target就是发送消息的Handler对象。而Looper对象又通过loop方法不断的循环消息,取出需要处理的消息,通过消息中关联的Handler对象分发消息(dispatchMessage)给对应的Handler来处理消息。

8.消息机制在android中的应用

8.1Android应用程序的主线程是以ActivityThread静态函数main()为入口

 public static void main(String[] args) { 
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.?Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");?    
 }

8.2Asynctask中的应用pre,post

private static class InternalHandler extends Handler {
    public InternalHandler() {
        super(Looper.getMainLooper());
    }

    @SuppressWarnings({ "unchecked", "RawUseOfParameterizedType" })
    @Override
    public void handleMessage(Message msg) {
        AsyncTaskResult result = (AsyncTaskResult) msg.obj;
        switch (msg.what) {
        case MESSAGE_POST_RESULT:
            // There is only one result
            result.mTask.finish(result.mData[0]);//这里的finish方法会调用到onPostExecute方法
            break;
        case MESSAGE_POST_PROGRESS:
            result.mTask.onProgressUpdate(result.mData);
            break;
        }
    }
}

    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);//onPostExecute方法是消息机制在handleMessage的时候回调的
        }
        mStatus = Status.FINISHED;
    }

    private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult(this, result));
        message.sendToTarget();
        return result;
    }

    @WorkerThread
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult(this, values)).sendToTarget();
        }
    }

注意onPreExecute用的并不是这种消息机制而是使用接口回调的方式来做的,这个方法是在主线程中被回调的,

    @MainThread
    public final AsyncTask executeOnExecutor(Executor exec,
            Params... params) { 
         。。。。。。
        onPreExecute();
        。。。。。。 
        exec.execute(mFuture); 
        return this;
    }

9.HandlerThread的用法

9.1为什么使用HandlerThread

在我们的应用程序当中为了实现同时完成多个任务,所以我们会在应用程序当中创建多个线程。为了让多个线程之间能够方便的通信,我们会使用Handler实现线程间的通信。
下面我们看看如何在线程当中实例化Handler,在线程中实例化Handler我们需要保证线程当中包含Looper(注意:UI-Thread默认包含Looper)。
为线程创建Looper的方法如下:在线程run()方法当中先调用Looper.prepare()初始化Looper,然后再run()方法最后调用Looper.loop(),这样我们就在该线程当中创建好Looper。 我们实现Looper有没有更加简单的方法呢?当然有,这就是我们的HandlerThread。(Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes)

9.2使用步骤

1.创建一个HandlerThread,即创建了一个包含Looper的线程。
HandlerThread handlerThread = new HandlerThread("leochin.com");
handlerThread.start(); //创建HandlerThread后一定要记得start()

2.获取HandlerThread的Looper
Looper looper = handlerThread.getLooper();

3.创建Handler,通过Looper初始化
Handler handler = new Handler(looper);

9.3使用HandlerThread实现简易的Asynctask

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;

public abstract class ThreadTask {

    private HandlerThread mHandlerThread;
    private TaskHandler mHandler;
    private TaskHandler mUiHandler;
    private Params[] mParams;

    public ThreadTask() {
        mHandlerThread = new HandlerThread("ThreadTask",
                android.os.Process.THREAD_PRIORITY_BACKGROUND);
        mHandlerThread.start();
        mHandler = new TaskHandler(mHandlerThread.getLooper());
        mUiHandler = new TaskHandler(Looper.getMainLooper());
    }

    protected abstract Result doInBackground(Params... params);

    protected void onPreExecute() {

    }

    protected void onProgressUpdate(Progress... values) {
    }

    protected final void publishProgress(Progress... values) {
        mUiHandler.obtainMessage(MESSAGE_PROGRESS, values).sendToTarget();
    }

    protected void onPostExecute(Result result) {
    }

    public final boolean isCancelled() {
        return mHandlerThread.isInterrupted();
    }

    public final void cancel(boolean mayInterruptIfRunning) {
        if (!mHandlerThread.isInterrupted()) {
            try {
                mHandlerThread.quit();
                mHandlerThread.interrupt();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        onCancelled();
    }

    protected void onCancelled() {
    }

    public void execute(Params... params) {
        mParams = params;
        onPreExecute();
        mHandler.sendEmptyMessage(MESSAGE_INBACKGROUND);
    }

    private static final int MESSAGE_INBACKGROUND = 0;
    private static final int MESSAGE_POSTEXECUTE = 1;
    private static final int MESSAGE_PROGRESS = 2;

    private class TaskHandler extends Handler {

        public TaskHandler(Looper looper) {
            super(looper);
        }

        @SuppressWarnings("unchecked")
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_INBACKGROUND:
                mUiHandler.obtainMessage(MESSAGE_POSTEXECUTE,
                        doInBackground(mParams)).sendToTarget();
                break;
            case MESSAGE_POSTEXECUTE:
                onPostExecute((Result) msg.obj);
                mHandlerThread.quit();
                break;
            case MESSAGE_PROGRESS:
                onProgressUpdate((Progress[]) msg.obj);
                break;
            }
        }
    }
}

9.4HandlerThread源码

/**
 * Handy class for starting a new thread that has a looper. The looper can then
 * be used to create handler classes. Note that start() must still be called.
 */
public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

    /**
     * 如果在loop之前需要做什麽操作就覆蓋整個方法再這裡執行
     */
    protected void onLooperPrepared() {

    }

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();//
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();// 囘調
        Looper.loop();
        mTid = -1;
    }

    /**
     * 
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        // If the thread has been started, wait until the looper has been
        // created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

你可能感兴趣的:(android消息机制)