1、Handler简介

Handler是Android的一种消息机制,用于同一进程的线程间通信,在这里引用一些任老师书里的描述。 Handler的主要作用是将一个任务切换到某个指定的线程中去执行。那么Android为什么要提供这个功能呢?那是因为Android规定访问UI只 能在主线程中进行,如果再子线程中访问UI,那么程序就会抛出异常(这个验证是否是主线程的工作在ViewRootImpl的checkThread方 法里完成)。这里说的主线程比较特殊,它是由Zygote fork创建的进程,程序入口是ActivityThread类的main方法,然而AcitvityThread不是一个Thread,只是一个final类,后面会有进一步说明。

void checkThread(){    if(mThread != Thread.currentThread){        throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views");  }}
为什么系统不允许子线程访问UI呢?那是因为Android的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可 预期的状态。那为什么系统不对UI控件的访问加上锁机制呢?有两个原因,首先加上锁机制会让UI访问的逻辑变得复杂;其次锁机制会降低UI访问的效率(例 如阻塞某些线程的执行)。因此最简单且高效的就是采用单线程模型来处理UI操作,这个单线程就是主线程,而开发者只需通过Handler机制切换到主线程 中去执行UI操作。例如,我们都知道的一个著名错误ANR,Android建议不要在主线程中进行耗时操作,否则会导致ANR,因此一般都会拉起一个线程来执行耗时操作,而这个耗时操作完后又要反映到UI的变化,此时我们就要用Handler,将UI的变化工作切换到主线程中去执行。最后,Android之所以提供 Handler,主要原因就是为了解决在子线程中无法访问UI的矛盾,而Handler并不是专门用于更新UI(例如HandlerThread的应用),它只 是常被开发者用来更新UI。

2、Handler机制梳理

平常我们说的Handler,指的是由Handler、Message、MessageQueue和Looper构成的一个整体运行机制。我们可以从下图,大概了解它们的运行流程。


首先就是Handler调用sendXXX系列或者postXXX系列的方法发送Message,不管是哪种方法都是需要从全局消息池里面拿出一个Message对象,即obtain(虽然Message有个全局消息池,其实它的内部实现只是一个对链头进行插入和删除的单链表,毕竟单链表在插入和删除上比较有优势),接着对该Message对象进行各种成员变量的赋值后,把它发送到相应线程的消息队列中,即enqueueMessage(虽然MessageQueue叫消息队列,但它的内部实现并不是队列,和全局消息池一样,也是一个对链头进行插入和删除的单链表),之后的工作交给相应线程的Looper对象,它通过调用loop()方法,无限循环地往消息队列里取消息,即next(),如果队列里无消息,它便被阻塞了(nativePollOnce和nativeWake,本地方法使用Linux的epoll模型)。如果有消息便把消息取出来,同时消息队列伴随着删除该消息的操作,然后调用Message对象的target成员变量的dispatchMessage方法进行消息分发处理,target实际上就是Handler的实例。Handler把消息处理完后,Looper便要把这条消息进行回收再利用,即recycle(),对消息进行“净身”,即置空消息的所有成员变量,之后保证消息无污染地插入全局消息池中,避免OOM。

3、Handler机制分析

大家读到这里有没有产生这样的疑问,上面提到相应线程的消息队列和相应线程的Looper对象,Handler发送消息它是怎么识别发送到哪个线程中的消息队列呢?下面我写了个小例子,我们跟着代码分析。
public class TestHandler extends Handler {public static final String TAG = "TestHanlder";private String mName = null;public TestHandler(String n) {// TODO Auto-generated constructor stubmName = n;}public TestHandler(String n, Looper lp){super(lp);mName = n;}@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubswitch(msg.what){case 1:Log.d(TAG, mName);break;default:break;}}}
这里我写的一个比较简单的继承于Handler的TestHandler类,接下来在界面xml里声明一个button,在mainActivity对这个button的点击事件进行处理,处理里new一个TestHandler对象并发送消息。
public void button1(View v){TestHandler th = new TestHandler("button1");Log.d(TAG,th.getLooper().getThread().toString());th.sendEmptyMessage(1);}
点击按钮后打印信息如下:
09-17 17:17:09.879: D/MainActivity(21186): Thread[main,5,main]09-17 17:17:09.879: D/TestHanlder(21186): button1
这里new一个TestHandler实例后,我打印出与该实例所绑定的线程名称,通过log可看成,这个线程是主线程,接着后面的sendEmptyMessage方法就是把消息发送给主线程的,问题来了,TestHandler是怎么知道要把消息发送给主线程的。我们可以看看TestHandler的构造方法,虽然方法里只是简单的对mName进行赋值,但它隐藏了一个段代码,即隐式地调用了父类的构造方法super()。TestHandler的父类是Handler,接下我们看看Handler源码,它的构造方法里都做了什么。
    /**     * 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);    }    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;    }
这里看到Handler类有两个成员变量mLooper和mQueue,它们代表着TestHandler消息发往的消息队列和循环消息处理的Looper。其中mQueue是mLooper的成员变量,姑且不管,我们看看mLooper是怎么赋值的。
static final ThreadLocal sThreadLocal = new ThreadLocal();final MessageQueue mQueue;  ... ... .../**     * Return the Looper object associated with the current thread.  Returns     * null if the calling thread is not associated with a Looper.     */    public static Looper myLooper() {        return sThreadLocal.get();    }
这里涉及到一个ThreadLocal类,相关使用和原理大家可以去搜索了解一下。简单说,这里ThreadLocal就是类似于Map,其中Key是线程对象,而Value就是Looper对象。这里sThreadLocal.get(),Key就是当前线程,该方法返回当前线程对应的Looper对象。当然如果当前线程没有Looper对象,Handler就会抛出异常,也就是我们常见“Can't create handler inside thread that has not called Looper.prepare()”。话说回来了,new一个TestHandler实例时候是在MainActivity里,当前线程当然是主线程,于是这个TestHandler在构造时就与主线程的Looper和MessageQueue绑定了,只要其他线程能获取该TestHandler实例来发送消息,消息便能发送到主线程的队列里,从而促发主线程的Looper调用Handler处理消息,这就是切换到主线程进行UI操作,而TestHandler类,如其名Handler——处理者,里面实际就包含了你自己写的,要做什么UI的处理操作,这里只是简单的一句log打印。这里留一个疑问,上面说过,如果当前线程没有Looper对象,Handler就会抛出异常,那么主线程是什么时候拥有Looper对象的?这个问题和开篇说的ActivityThread有关系,后面说。
从上面我可以知道,Looper不断循环取消息并处理,其中处理操作其实就是调用了Handler的dispatchMessage方法,由Handler进行消息分发处理,我们看看Handler分发消息的实现:
    /**     * 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);        }    }
既然Handler对消息进行分发处理,那么都有哪些处理者接受Handler的分发呢?从上面代码中看到,有三个处理者,分别是msg.callback、mCallback和handleMessage()。首先msg.callback是什么,接着看Handler源码:
    public final boolean post(Runnable r)    {       return  sendMessageDelayed(getPostMessage(r), 0);    }    public final boolean postAtTime(Runnable r, long uptimeMillis)    {        return sendMessageAtTime(getPostMessage(r), uptimeMillis);    }... ... ...    private static Message getPostMessage(Runnable r) {        Message m = Message.obtain();        m.callback = r;        return m;    }    private static Message getPostMessage(Runnable r, Object token) {        Message m = Message.obtain();        m.obj = token;        m.callback = r;        return m;    }    private static void handleCallback(Message message) {        message.callback.run();    }
看上面我粘贴的部分关键源码可知,msg.callback就是postXXX系列方法传入进来的Runnable对象,消息处理在该对象的run方法里进行。接着我们看第二位处理者mCallback,在Handler源码里:
     /**     * 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);    }    ... ... ...   public Handler(Callback callback) {        this(callback, false);    } /**     * 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);    }... ... ...    final Callback mCallback;
由此可知,mCallback是Callback接口,需要实现它的handleMessage方法来处理消息,它的存在就是为我们提供另一种使用Handler的方式,如注释说的创建一个Handler实例但并不需要派生Handler子类。剩下的第三位处理者就是继承Handler并重写handleMessage方法的子类对象,也是我们平常用的较多的,就像上面例子中的Testhandler一样,继承了Hnadler,重写了handleMessage方法,方法里打印了button1。
接下来我们可以看看非主线程是如何具有Handler机制,还是例子分析,和上面工程一样,只是添加了个button2按钮和一个TestHandlerThreadHelp类,首先我们看button2的调用代码,如下:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TestHanlderThreadHelp.getInstance().starTest("MyTestHandler");}        public void button2(View v){ TestHandler th = TestHanlderThreadHelp.getInstance().getHandlerInMyThread("button2");Log.d(TAG,th.getLooper().getThread().toString()); th.sendEmptyMessage(1);}@Overrideprotected void onDestroy() { // TODO Auto-generated method stubsuper.onDestroy();TestHanlderThreadHelp.getInstance().stopTest();}
TestHandlerThreadHelp类实现了单例模式,它有一个内部线程类TestHandlerThread,这里的getHandlerInMyThread方法是获取一个与TestHandlerThread线程绑定了的Handler实例对象,然后在主线程里发送消息,在TestHandlerThread线程里进行消息处理。在mainActivity的onCreate()方法里startTest(),里面新建一个TestHandlerThread对象,然后start()开启线程跑起来。在onDestroy()方法里stopTest(),做一些释放工作。接下来看看TestHandlerThreadHelp的实现:
public class TestHanlderThreadHelp {public static final String TAG = "TestHanlderThreadHelp";private TestHanlderThread mtht = null;private TestHandler th = null;private TestHanlderThreadHelp() {}private static class TestHanlderThreadHelpHolder {private static final TestHanlderThreadHelp mInstance = new TestHanlderThreadHelp();}public static TestHanlderThreadHelp getInstance(){return TestHanlderThreadHelpHolder.mInstance;}public TestHandler getHandlerInMyThread(String n){if(th == null)th = new TestHandler(n,mtht.getLooper());return th;}public void starTest(String threadName){if(mtht == null)mtht = new TestHanlderThread(threadName);mtht.start();}public void stopTest(){if(mtht != null)mtht.quit();mtht = null;                th = null; }private class TestHanlderThread extends Thread{Looper mLooper;public TestHanlderThread(String threadName) {// TODO Auto-generated constructor stubsuper(threadName);}@Overridepublic void run() {// TODO Auto-generated method stub//super.run();Looper.prepare();mLooper = Looper.myLooper();Looper.loop();}public Looper getLooper(){if(!isAlive())return null;return mLooper;}public boolean quit(){Looper lp = getLooper();if(lp != null){lp.quit();return true;}return false;}}}
点击按钮后打印的log信息:
09-18 10:34:37.689: D/MainActivity(21695): Thread[MyTestHandler,5,main]09-18 10:34:37.699: D/TestHanlder(21838): button2
这里我们看到打印出来与TestHandler实例绑定的线程名称,就是我们new一个TestHandlerThread线程对象时的传入名称MyTestHandler,button2的打印就在MyTestHandler线程里执行的。从之前Handler运行流程图,我们知道一个独立的线程要具有Handler处理机制,那么它就要有自己的消息队列并且有Looper在循环处理。这也就是TestHandlerThread的run方法里面要做的工作,对应分别是Looper.prepare()和Looper.loop(),它们是必须的。接下来我们看看Looper源码:
     /** Initialize the current thread as a looper.      * This gives you a chance to create handlers that then reference      * this looper, before actually starting the loop. Be sure to call      * {@link #loop()} after calling this method, and end it by calling      * {@link #quit()}.      */    public static void prepare() {        prepare(true);    }    private static void prepare(boolean quitAllowed) {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper(quitAllowed));    }... ... ...    private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }
Looper.prepare()工作就是,如果当前线程没有Looper对象的话,就为当前线程new一个Looper对象,这里的sThreadLocal.set方法,简单理解就是保存一个键值对,key是当前线程对象,value是new出来的Looper对象。和它相反的之前提过的,就是sThreadLocal.get(),在Looper.myLooper()方法里,表示取出key是当前线程的Looper对象。而在Looper的构造函数里,new了一个属于该Looper对象的MessageQueue对象,也就是说,Looper对象与MessageQueue对象绑定了,只要获取相应线程的Looper对象,就能获取Looper对象对应的消息队列。最后就是Looper.loop()了,里面代码太长就不贴上来了,这个方法可以简单理解为,它从消息队列里取一个消息并处理,完后再取下一个消息再处理,周而复始地工作,如果消息队列里无消息了,它就会被阻塞了,释放资源进行休眠,一旦有消息来了就要被唤醒并重新开始工作,除了主线程外,loop是可以退出的,而退出死循环的方法就是取消息的next()返回空,除了主线程的Looper外,其他线程的Looper都可以 通过quit方法进行退出,TestHandlerThread类里面提供的退出loop的方法就是调用了Looper的quit方法,它的实现很简单,就是调用MessageQueue的quit方法,从而使得MessageQueue的next()方法返回空,这时候loop()方法的死循环就跳出来了,从而线程运行结束并销毁。运行这两个方法之后,我们的MyTestHandler线程就是一个具有Handler消息处理机制的线程了。
然而这里还是有问题的,问题是我们怎么把消息发到MyTestHandler线程的消息队列里呢?也就是说,我们在new一个Handler实例时怎么绑定MyTestHandler线程对应的Looper对象呢?于是TestHandlerThread类里就有了一个mLooper成员变量及其getter方法,用于存储和获取TestHandlerThread线程对应的Looper对象。在new一个Handler实例时,Hanlder有一个构造方法Handler(Looper),作用就是把Handler实例就与传入的Looper对象绑定在一起了,此后它的发送消息就会发到与这个Looper对象对应的线程里。因此在程序里,我写了个包装了TestHandlerThread类的TestHandlerThreadHelp类,它的getHandlerInMyThread方法里就返回了绑定了TestHandlerThread线程的Handler实例。至此,其他线程只要拿到这个实例,就能往TestHandlerThread线程发送消息了。因此,我们在mainActivity的button2方法里,调用TestHandlerThreadHelp类的getHandlerInMyThread方法获取Handler实例并发送消息,效果等于在主线程里往MyTestHandler线程发送消息,最后在MyTestHandler线程里处理消息。这里写的TestHandlerThread类仅仅为了测试验证所写,实际使用中,还是推荐使用android系统现成提供的HandlerThread类,使用方式如下:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);h = new HandlerThread("MyTestHandler3");h.start();}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();h.quit();}public void button3(View v){TestHandler th = new TestHandler("button3", h.getLooper());Log.d(TAG,th.getLooper().getThread().toString());th.sendEmptyMessage(1);}
mainActivity里面添加一个button3,点击事件处理就是HandlerThread的使用。首先HandlerThread被new出来后,要star()开启它,含有Handler处理机制的线程才算正真运行起来,看看HandlerThread类的run方法:
    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }
和我们之前写的TestHandlerThread大同小异,一样的要Looper.prepare()和Looper.loop(),但它严谨些,添加了同步机制,同样也是提供了可以获取该线程的Looper对象的接口getLooper()。因此在oncreate()方法里new的HandlerThread对象并stat()开启,我们的MyTestHandler3线程就在等待消息处理了。button3方法里new出来的TestHandler实例时,传入MyTestHandler3线程的Looper对象与其进行绑定,之后使用该实例发送消息,就能直接发给MyTestHandler3线程中去处理了。点击按钮后打印信息如下:
09-18 14:43:59.279: D/MainActivity(21695): Thread[MyTestHandler3,5,main]09-18 14:43:59.279: D/TestHanlder(21839): button3
运行整个工程后,使用eclipse的DDMS找到该工程的进程,一般为它的包名,接着打开它的线程列表,可以看到MyTestHandler和MyTestHandler3这两个线程已经被拉起并在等待消息处理,注意到它们的线程号和打印button2和button3时的线程号一样,说明了Handler处理已经真正切换到了该线程中处理了;
1    21695    Native    72    52    main    *2    21697    VmWait    144    7    GC    *3    21700    VmWait    0    0    Signal Catcher    *4    21701    Runnable    2267    6275    JDWP    *5    21702    VmWait    4    2    Compiler    *6    21703    Wait    0    0    ReferenceQueueDaemon    *7    21704    Wait    1    0    FinalizerDaemon    *8    21705    Wait    0    0    FinalizerWatchdogDaemon    9    21706    Native    0    1    Binder_1    10    21707    Native    0    0    Binder_2    11    21838    Native    0    0    MyTestHandler    12    21839    Native    0    0    MyTestHandler3    13    21841    Native    0    0    Binder_3    

最后,在前面叙述中,留下了一个疑问,那就是主线程是什么时候拥有Looper对象的?当启动一个应用程序的时候,系统为应用程序创建进程时会传入一个java类(ActivityThread类),把该类的静态成员函数main作为程序运行入口点。而主线程是在应用程序进程开启后第一个被启动的线程,用来执行ActivityThread的main方法。在开始的时候提过,主线程比较特殊,它不像其他线程一样new出来了之后再start开启,它是由底层zygota fork出来并把AcitvityThread类main方法作为入口而跑起来的线程,ThreadActivity类也不是一个Thread,它只是一个final类,下面我们看看ActivityThread的main方法实现:
    public static void main(String[] args) {          SamplingProfilerIntegration.start();            // CloseGuard defaults to true and can be quite spammy.  We          // disable it here, but selectively enable it later (via          // StrictMode) on debug builds, but using DropBox, not logs.          CloseGuard.setEnabled(false);            Environment.initForCurrentUser();            // Set the reporter for event logging in libcore          EventLogger.setReporter(new EventLoggingReporter());            Process.setArgV0("");            Looper.prepareMainLooper();            ActivityThread thread = new ActivityThread();          thread.attach(false);            if (sMainThreadHandler == null) {              sMainThreadHandler = thread.getHandler();          }            AsyncTask.init();            if (false) {              Looper.myLooper().setMessageLogging(new                      LogPrinter(Log.DEBUG, "ActivityThread"));          }            Looper.loop();            throw new RuntimeException("Main thread loop unexpectedly exited");      }  }  
这里我们看到了Looper.prepareMainLooper()和Looper.loop(),因为是主线程比较特殊,Looper还专门提供了一个prepareMainLooper方法专门用于主线程的prepare,不过该方法与非主线程的prepare方法大同小异。接下来看看Looper里面prepareMainLooper方法实现:
     /** Returns the application's main looper, which lives in the main thread of the application.     */    public static Looper getMainLooper() {        synchronized (Looper.class) {            return sMainLooper;        }    }... ... ... /** Initialize the current thread as a looper.      * This gives you a chance to create handlers that then reference      * this looper, before actually starting the loop. Be sure to call      * {@link #loop()} after calling this method, and end it by calling      * {@link #quit()}.      */    public static void prepare() {        prepare(true);    }    private static void prepare(boolean quitAllowed) {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper(quitAllowed));    }    /**     * 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();        }    }
这里可以 对比一下非主线程的prepare和主线程prepare的区别,主线程new出来的Looper对象传入的quitAllowed参数是false,代表着它的loop()是不允许被退出的。另外Looper类有一个成员变量mMainLooper,指向主线程的Looper对象,在prepareMainLooper()里被赋值,而且还对外提供了getMainLooper()方法,通过它可以在任何地方获得到主线程的Looper对象。Looper.prepareMainLooper()和Looper.loop()之后,主线程就可以接收并处理Handler消息了。我们知道Activity的生命周期中的onCreate、onResume和onPause等方法都是在主线程中执行的,然而这里的主线程一直在死循环里监听和处理Handler消息,它怎么去做这些事情的?很简单,往主线程里发相应的Handler消息,在主线程里触发Activity生命周期的相应操作。ActivityThread类为此提供了getHandler方法,该方法返回一个与主线程绑定的H实例,而H继承了Handler类,是ActivityThread类的内部类,代码实现如下:
... ...final H mH = new H();... ...final Handler getHandler() {        return mH;}... ...private class H extends Handler {public static final int LAUNCH_ACTIVITY         = 100;public static final int PAUSE_ACTIVITY          = 101;public static final int PAUSE_ACTIVITY_FINISHING= 102;public static final int STOP_ACTIVITY_SHOW      = 103;        public static final int STOP_ACTIVITY_HIDE      = 104;public static final int SHOW_WINDOW             = 105;public static final int HIDE_WINDOW             = 106;public static final int RESUME_ACTIVITY         = 107;public static final int SEND_RESULT             = 108;public static final int DESTROY_ACTIVITY        = 109;... ...public void handleMessage(Message msg) {            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));            switch (msg.what) {                case LAUNCH_ACTIVITY: {                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;                    r.packageInfo = getPackageInfoNoCheck(                            r.activityInfo.applicationInfo, r.compatInfo);                    handleLaunchActivity(r, null);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                } break;                case RELAUNCH_ACTIVITY: {                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;                    handleRelaunchActivity(r);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                } break;                case PAUSE_ACTIVITY:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,                            (msg.arg1&2) != 0);                    maybeSnapshot();                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;... ...
从这可以看到Activity生命周期的相关操作都是在H类的handlerMessage里,只要通过getHandler方法拿到H实例并发送相应消息就可以触发相应操作。那么会有谁来调用getHandler方法来发送这些消息呢?这里涉及到Android系统startActivity的流程及其binder通信,Handler机制只是它们实现中而使用到的一个部分。接下来截取下知乎上一位大神描述的一个例子: 从进程与线程间通信的角度,通过一张图加深大家对App运行过程的理解: system_server进程是系统进程,java framework框架的核心载体,里面运行了大量的系统服务,比如这里提供ApplicationThreadProxy(简称ATP),ActivityManagerService(简称AMS),这个两个服务都运行在system_server进程的不同线程中,由于ATP和AMS都是基于IBinder接口,都是binder线程,binder线程的创建与销毁都是由binder驱动来决定的。 App进程则是我们常说的应用程序,主线程主要负责Activity/Service等组件的生命周期以及UI相关操作都运行在这个线程; 另外,每个App进程中至少会有两个binder线程 ApplicationThread(简称AT)和ActivityManagerProxy(简称AMP),除了图中画的线程,其中还有很多线程,比如signal catcher线程等,这里就不一一列举。Binder用于不同进程之间通信,由一个进程的Binder客户端向另一个进程的服务端发送事务,比如图中线程2向线程4发送事务;而handler用于同一个进程中不同线程的通信,比如图中线程4向主线程发送消息。 结合图说说Activity生命周期,比如暂停Activity,流程如下:
  1. 线程1的AMS中调用线程2的ATP;(由于同一个进程的线程间资源共享,可以相互直接调用,但需要注意多线程并发问题)
  2. 线程2通过binder传输到App进程的线程4;
  3. 线程4通过handler消息机制,将暂停Activity的消息发送给主线程;
  4. 主线程在looper.loop()中循环遍历消息,当收到暂停Activity的消息时,便将消息分发给ActivityThread.H.handleMessage()方法,再经过方法的调用,最后便会调用到Activity.onPause(),当onPause()处理完后,继续循环loop下去。
链接:http://www.zhihu.com/question/34652589/answer/90344494    来源:知乎binder客户端就是一个线程,在ActivityThread的main方法里, thread.attach(false)来创建,在上述提过使用ddms打开一个进程的线程列表,列表里有些binder_1、binder_2和binder_3就是这些线程。至此对Handler机制总结一下:Handler用于同一进程里线程间的通信,作用是将一个任务切换到某个指定的线程中去执行。然而Handler并不是专门用于更新UI,它只是常被开发者用来更新UI。例如我们可以内部运行一个拥有Handler机制功能的非UI线程(HandlerThread类使用),作为一个业务逻辑入口,消息处理里实现调用相关业务功能。UI上调用业务逻辑功能都要通过这个业务逻辑入口,即往这个非UI线程发送handler消息,这样利于代码组织结构清晰。

------------------------- 2016/11/29--------------------------在研究android内存泄漏时,发现有一种handler的使用方法会导致内存泄漏,这里简单记一下,具体如下例子:
public class HandlerActivity extends Activity {        private final Handler mHandler = new Handler() {          @Override          public void handleMessage(Message msg) {              // ...          }      };        @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          mHandler.sendMessageDelayed(Message.obtain(), 60000);            //just finish this activity          finish();      }    }  
这里的mHandler是HandlerActivity类的内部匿名类,java的内部匿名类在构造时,编译器会隐性地加上一个引用类型的成员变量,该成员变量会指向HandlerActivity。接在HandlerActivity在oncreate的时候给了一个handler消息后finish掉自己了。此时内部匿名类一直持有着HandlerActivity的实例,因此该activity不会被GC回收。这里有一个疑问,它是内部类,外部类退出了内部类也一样会被销毁,但这里没有被销毁是因为,Message类引用了mHandler实例。在loop循环中被取到拿出来处理时,message对象引用着的mHandler,就是消息处理操作。只有消息处理操作完成,在loop方法最后调用Message的recyclerUnchecked方法,才把引用置空。上面例子发送了handler消息,它还没来得及处理,activity就退出,它持有的资源就不会得到释放,造成内存泄漏。可通过静态Handler内部类,handler外部类,handler里持有activity的弱引用 或 使用application的context。activity退出后,如果要处理的消息操作没有意义了,可在ondestroy里remove掉。部分例子如下:
public class HandlerActivity2 extends Activity {        private static final int MESSAGE_1 = 1;      private static final int MESSAGE_2 = 2;      private static final int MESSAGE_3 = 3;      private final Handler mHandler = new MyHandler(this);        @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          mHandler.sendMessageDelayed(Message.obtain(), 60000);            // just finish this activity          finish();      }        @Override      public void onDestroy() {      //  If null, all callbacks and messages will be removed.      mHandler.removeCallbacksAndMessages(null);  }     public void todo() {      };        private static class MyHandler extends Handler {          private final WeakReference mActivity;            public MyHandler(HandlerActivity2 activity) {              mActivity = new WeakReference(activity);          }            @Override          public void handleMessage(Message msg) {              System.out.println(msg);              if (mActivity.get() == null) {                  return;              }              mActivity.get().todo();          }      } 
------------------------- 2018/7/4-------------------------- Handler扩展
1、Handler的消息队列是按照时间排序的(msg.when时间参数,以system boot为基准),时间最短的排的越靠近接口。
2、removeMessage只能移除消息队列里的消息,已经被next出去并进行处理的是无法取消的。 3、msg.what尽量不使用0,因为postDelayed(runnable, time)默认创建的msg的what就是0,一旦removeMessage,就会把所有msg.what等于0的消息移除,这样runnable也会被移除。
4、SyncBarrier消息就是一个target为null的message,一旦发送syncbarrier消息,那么这个消息后续的说有同步消息都不会被执行,只有异步消息才能通过被执行,提供了一个简单的优先级机制。MessageQueue的next方法如下:
 // 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)                         ... ... ...

5、MessageQueue的IdleHandler接口用于在looper处理完所有消息并空闲时被调用,接口返回true表示下次空闲时可被再此调用,返回false就执行一次就完。









更多相关文章

  1. Android中Broadcast Receiver组件详解
  2. Android消息机制(一):主要流程与原理解析
  3. android Handle
  4. Android(安卓)之 sms 短信
  5. android中的进程与线程的理解
  6. android多线程机制
  7. Android的schedule、AlarmService、Timer定时器机制
  8. android消息处理——Thread、Looper、Handler
  9. Android(安卓)View 绘制刷新流程分析

随机推荐

  1. JAVA & Android 系统环境变量配置
  2. Android 7.1 去掉桌面上的谷歌搜索框
  3. Android实时获得周围wifi信息(SSID,强度等)
  4. android 塔防游戏汇总 及android 游戏开
  5. 【Android】【Framework】Android_Framew
  6. android图片切换ImageSwichter的动画切换
  7. Android Shape 详解
  8. android热修复--阿里热修复使用和源码分
  9. android 背景图片
  10. android http 请求方式