A Handler allows you to send and processMessageand Runnable objects associated with a thread'sMessageQueue. 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.

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.

Scheduling messages is accomplished with thepost(Runnable),postAtTime(Runnable, long),postDelayed(Runnable, long),sendEmptyMessage(int),sendMessage(Message),sendMessageAtTime(Message, long), andsendMessageDelayed(Message, long)methods. Thepostversions allow you to enqueue Runnable objects to be called by the message queue when they are received; thesendMessageversions allow you to enqueue aMessageobject containing a bundle of data that will be processed by the Handler'shandleMessage(Message)method (requiring that you implement a subclass of Handler).

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.

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 samepostorsendMessagemethods 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创建过程中,会默认绑定一个线程的thread/message queue,这个就可以发送messages或者runnables到message queue,然后处理它们 问题一: 如何绑定thread/message的
第二段,Handler的二个主要的使用方法: 1、定时发送messages和runnables 2、把一个即将执行的action加入到其它线程的message queue中,而不是自己的线程 问题二:如果理解第二个方法
第三四段,讲了handler的处理流程,以及方法的介绍
最后 一段,当一个application的进程被创建,main thread就会运行一个message queue管理一些顶级的应用对象 activities, broadcast receivers 等等。 当然我们也可以创建自己的线程,通过handler和main thread交互,方法就是在自己新的线程上调用handler的方法。 问题三:如何创建新的线程,用handler和main thread交互。
这篇解决问题一:handler是如何绑定thread/message的
                                   private TextView textView;                            private static final String TAG = SecondActivity.class.getSimpleName();                            private static final int EMPTY_MSG = 0;                            private static final int MSG_ONE = 1;                            private Handler handler = new Handler(new Handler.Callback() {                            @Override                            public boolean handleMessage(Message msg) {                            Log.d(TAG,"no further handling is desired");                            return false;                            }                            }){                            @Override                            public void handleMessage(Message msg) {                            switch (msg.what){                            case EMPTY_MSG:                            Log.d(TAG,"Handler Thread : " + Thread.currentThread().getId());                            Log.d(TAG,"Empty Message");                            break;                            case MSG_ONE:                            Person person = (Person) msg.obj;                            textView.setText("arg1 = " + msg.arg1 + " ,arg2 = " + msg.arg2 + " ,Person = " + person);                            break;                            }                            super.handleMessage(msg);                            }                            };                            @Override                            protected void onCreate(Bundle savedInstanceState) {                            super.onCreate(savedInstanceState);                            setContentView(R.layout.second);                            textView = (TextView) findViewById(R.id.tv);                            Log.d(TAG, "UI Thread : " + Thread.currentThread().getId());                            Message msg = new Message();                            msg.what = MSG_ONE;                            msg.arg1 = 1;                            msg.arg2 = 2;                            msg.obj = new Person("David",23);                            handler.sendMessage(msg);                            }                                                       class Person{                            public Person(String name,int age){                            this.name = name;                            this.age = age;                            }                            public String name;                            public int age;                                                       @Override                            public String toString() {                            return "name = " + name + " ,age = " + age;                            }                            }                 


从上面的可以看到,创建Handler会默认绑定一个线程或者消息队列,那么Handler到底绑定哪个线程呢,从LOG中我们可以看到默认绑定的是UI Thread,但是有的人会问如果我创建一个新的Thread,然后在里面创一个Handler,那么是不是就是默认绑定当前线程呢,其实并不是这样,我们看下Handler的构造方法 ,最终会调动如下的构造函数
                                                   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关联了一个Looper对象,而且这个Looper对象不能为空,不然会提示异常 Can't create handler inside thread that has not called Looper.prepare() ,而且MessageQueue对象就是从Looper对象中来的, 而且Handler还关联了一个Callback接口mCallback 现在看看Looper.myLooper()
                                                   /**                                  * 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       ();                                         }                      
再看下由构造函数传进来的Callback是什么,就是个接口,从下面注释可以看到,如果接口中的方法返回true,就不用实现子类Handler的public void HandleMessage方法,相当于截断了事件 看下这个Callback接口
                                                     /**                                        * 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);                                        }                           

总结下Handler创建过程中都做了什么,获取了当前线程的mLooper, mQueue, 以及由构造方法传进来的Callback对象mCallback


从注释就可以看到当前返回的是当前线程的Looper对象,实际上在Acitivity创建的过程中,ActivityThread就帮我们创建了Looper对象,并保存到了sThreadLocal中 , 而这个Looper对象正是如异常提示中一样,由Looper.prepare()创建。
                                            /** 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));                                  }                      
从注释我们可以看到,Looper.prepare是初始化一个Looper对象,但是一个线程中只能有一个Looper对象,而且保存在sThreadLocal中,在创建Looper对象后,要调用loop()方法,并且先销毁它时候用quit()方法 再看下loope()到底在干嘛
                                            public static void loop() {                                  final Looper me = myLooper();                                  if (me == null) {                                  throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");                                  }                                  final MessageQueue queue = me.mQueue;                                                                   // Make sure the identity of this thread is that of the local process,                                  // and keep track of what that identity token actually is.                                  Binder.clearCallingIdentity();                                  final long ident = Binder.clearCallingIdentity();                                                                   //无线循环                                  for (;;) {                                  //取出下一个Message                                  Message msg = queue.next(); // might block                                  if (msg == null) {                                  // No message indicates that the message queue is quitting.                                  return;                                  }                                                                   // This must be in a local variable, in case a UI event sets the logger                                  Printer logging = me.mLogging;                                  if (logging != null) {                                  logging.println(">>>>> Dispatching to " + msg.target + " " +                                  msg.callback + ": " + msg.what);                                  }                                                                   msg.target.dispatchMessage(msg);                                                                   if (logging != null) {                                  logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);                                  }                                                                   // Make sure that during the course of dispatching the                                  // identity of the thread wasn't corrupted.                                  final long newIdent = Binder.clearCallingIdentity();                                  if (ident != newIdent) {                                  Log.wtf(TAG, "Thread identity changed from 0x"                                  + Long.toHexString(ident) + " to 0x"                                  + Long.toHexString(newIdent) + " while dispatching to "                                  + msg.target.getClass().getName() + " "                                  + msg.callback + " what=" + msg.what);                                  }                                                                   msg.recycleUnchecked();                                  }                                  }                      
从上面可以看到,通过一个无限循环,不断从MessageQueue中取出Message,如果Message为空就block,如果不是就msg.target.dispatchMessage(msg)把消息分配给target处理,其实这个target就是Handler自己,后面我们会看到这个,那么dispatchMessage又做了什么呢
                                            /**                                  * 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);                                  }                                  }                      
msg.callback,这个callback又是什么,在Message.java中是这样定义的
                                           /*package*/ Runnable callback;                      
很明显是一个Runnable对象,这里当然为空,那什么时候不为空呢,handler.post(new runnable()) ,这样是不是就不为空了。再看else的判断 ,mCallback前面已经说明了,所以只要这个mCallback.handleMessage(msg)返回值为false就也就正常执行handler的handleMessage(msg)方法
现在我们总结下,创建Handler的时候,会绑定当前线程的Looper对象,如果Looper对象为null,就会抛出异常 Can't create handler inside thread that has not called Looper.prepare() 而当前线程的Looper对象是由Looper.prepare创建。
Handler的构造方法看完了,我们就看下Message对象的创建 以及sendMessage(msg)方法 首先看Message的创建
                                           public final class Message implements Parcelable{                                  public Message() {                                  }                                 }                      
Message实现了Parcelable,稍微看下object,可以供参考
                                            /**                                  * An arbitrary object to send to the recipient. When using                                  * {@link Messenger} to send the message across processes this can only                                  * be non-null if it contains a Parcelable of a framework class (not one                                  * implemented by the application). For other data transfer use                                  * {@link #setData}.                                  *                                   * <p>Note that Parcelable objects here are not supported prior to                                  * the {@link android.os.Build.VERSION_CODES#FROYO} release.                                  */                                  public Object obj;                      

再看下sendMessage(msg)方法
                                            public final boolean sendMessageDelayed(Message msg, long delayMillis)                                  {                                  if (delayMillis < 0) {                                  delayMillis = 0;                                  }                                  return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);                                  }                      
                                                     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,我们在初始化Hanlder的时候就有了
                                            private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {                                  msg.target = this;                                  if (mAsynchronous) {                                  msg.setAsynchronous(true);                                  }                                  return queue.enqueueMessage(msg, uptimeMillis);                                  }                      
这个时候msg.target就出现了,就是我们创建的Handler对象 handler ,后面就不用分析了,加入到了mQueue中了,后面就是Looper的Loop()方法了不断的取出消息,发送到target,也就是handler,处理了,到此,整个Handler处理Message大致过程就分析完毕 ,至于其他的方法,都是类似分析

更多相关文章

  1. ch020 Android(安卓)SQLite3(第一部分)
  2. ch020 Android(安卓)SQLite3(第一部分)
  3. android 实现序列化 浅析一
  4. Android实现DES对字符串加密
  5. Android中Parcelable接口用法
  6. android 特效资源
  7. ANDROID轻量级JSON序列化和反序列化[转]
  8. android页面间传递对象
  9. android 播放视频保存的一些网页

随机推荐

  1. android 重用 c代码
  2. android studio 中一些比较好的插件
  3. 系出名门Android(4) - 活动(Activity),
  4. Android(安卓)HDMI( 三)
  5. Android中TextVIew一些属性
  6. Android(安卓)支持多屏幕机制
  7. Android(安卓)中文 API (102)—— CursorAd
  8. Android网络应用接口
  9. 系出名门Android(5) - 控件(View)
  10. Android(安卓)Studio加速