Android-初识Handler,Looper,Message(-) 源码

来源:互联网 发布:淘宝企业采购 编辑:程序博客网 时间:2024/05/21 11:11

本文只是表面的带大家浏览下Handler,Looper,Message的源码

android的消息处理有三个核心类:Looper,Handler和Message。其实还有一个Message Queue(消息队列),

异步处理大师 Handler:

什么是handler?handler扮演了往MQ上添加消息和处理消息的角色(只处理由自己发出的消息),即通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。handler创建时会关联一个looper,默认的构造方法将关联当前线程的looper,不过这也是可以set的。默认的构造方法:

public class handler {         final MessageQueue mQueue;  // 关联的MQ       final Looper mLooper;  // 关联的looper       final Callback mCallback;       // 其他属性         public Handler() {           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());               }           }           // 默认将关联当前线程的looper           mLooper = Looper.myLooper();           // looper不能为空,即该默认的构造方法只能在looper线程中使用   
        //UI主线程中默认带有一个Looper        if (mLooper == null) {               throw new RuntimeException(//不能在没有Looper的线程上创建Handler,                   "Can't create handler inside thread that has not called Looper.prepare()");           }           // 重要!!!直接把关联looper的MQ作为自己的MQ,因此它的消息将发送到关联looper的MQ上           mQueue = mLooper.mQueue;           mCallback = null;       }         // 其他方法   }  

当然这只是Handler的一个构造方法。Handler本身有四个构造函数,其他其他的三个你可以通过查看源码来解析,大致雷同。

Handler发送消息

有了handler之后,我们就可以使用 post(Runnabl),sendMessage(Message)这些方法向MQ上发送消息了。光看这些API你可能会觉得handler能发两种消息,一种是Runnable对象,一种是message对象,这是直观的理解,但其实post发出的Runnable对象最后都被封装成message对象了,见源码:
Post发送的形式

public final boolean post(Runnable r){//使用Post发送消息      return  sendMessageDelayed(getPostMessage(r), 0);}
private final Message getPostMessage(Runnable r) {//把一个Runnable包转成一个Message       Message m = Message.obtain();       m.callback = r;       return m;}
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){        boolean sent = false;        MessageQueue queue = mQueue;        if (queue != null) {
/*该handler对象,这确保了looper执行到该message时能找到处理它的handler,直白点就是ABC三个Handler发送消息,最终执行的时候Message消息
也是由他们本身来执行,而不会发生A接受到B发送的Message之类的情况*/            msg.target = this;//
            sent = queue.enqueueMessage(msg, uptimeMillis);//压入消息队列        }else {            RuntimeException e = new RuntimeException(                this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);        }        return sent;}

sendMessage(Message)形式

 public final boolean sendMessage(Message msg){        return sendMessageDelayed(msg, 0);}
public final boolean sendMessageDelayed(Message msg, long delayMillis){       if (delayMillis < 0) {           delayMillis = 0;       }       return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }

从源码中我们中我们可以很清晰的看到无论是用psot(Runnable)还是使用sendMessage(Message)方法,最后他们都会调用到同一个方法压入都一个队列中去。

Handler处理消息

那handler如何处理消息。消息的处理是通过核心方法是通过dispatchMessage(Message)来进行处理的,源码如下:

public void dispatchMessage(Message msg) {        if (msg.callback != null) {//post(Runnable)形式最终调用到这个方法            handleCallback(msg);        } else {
/* 这种方法允许让activity等来实现Handler.Callback接口或者构造Handler(Callback,避免了自己编写handler重写handleMessage方法*/            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);//优先等级最低的就是 重写HandlerMessage方法了        }    }

封装任务Message

Message的源码中没有特别的方法,对于Message我们应该记住下面的几个知识点(等待大家补充)

1.尽管我们可以直接instance一个Message,但我们最好通过Message.obtain()来从消息池中获得空消息对象,以节省资源。

2.如果你的message只需要携带简单的int信息,请优先使用Message.arg1和Message.arg2来传递信息,这比用Bundle更省内存

3.擅用message.what字段表示code,即这个消息具体是什么类型的消息.每个what都在其handlernamespace,我们只需要确保将由同一个handler处理的消息的what属性不重复就可以.相当于判别类型

4.message.When 它大小由小到大排列, 排在最前面的消息会首先得到处理,因此可以说消息队列并不是一个严格的先进先出的队列.

5.message.target 确定了最终你执行的时候由那个Handler来执行这个Message。一般来说谁压入队列就让谁在抽取出来的时候去执行。通过上面的源码我们可以查询到

Looper管道哥

首先明确一点Activity本身在启动的时候默认给了他一个Looper

Looper构造:

  private Looper() {        mQueue = new MessageQueue();//初始化Looper的时候的我们就给这个Looper配了一个MQ队列,一一对应        mRun = true;        mThread = Thread.currentThread();//绑定他所属的线程    }
 // 我们调用该方法会在调用线程的TLS中创建Looper对象       public static final void prepare() {           if (sThreadLocal.get() != null) {               // 试图在有Looper的线程中再次创建Looper将抛出异常               throw new RuntimeException("Only one Looper may be created per thread");           }           sThreadLocal.set(new Looper());       }   

 public static final void loop() {          Looper me = myLooper();//从该线程中取出对应的looper对象           MessageQueue queue = me.mQueue;//取消息队列对象...           while (true) {              Message msg = queue.next(); // might block 这个方法还不是很懂。出去一个待处理的Message              //if (!me.mRun) {            //    break;               //}               if (msg != null) {                  if (msg.target == null) {                      // No target is a magic identifier for the quit message.                       return;                  }                  if (me.mLogging!= null) me.mLogging.println(                          ">>>>> Dispatching to " + msg.target + " "                          + msg.callback + ": " + msg.what                          );                  msg.target.dispatchMessage(msg); //消息的抽取。最终的施行执行方法                if (me.mLogging!= null) me.mLogging.println(                          "<<<<< Finished to    " + msg.target + " "                          + msg.callback);                  msg.recycle();              }          }      }  

以上就是对Handler和Message还有Looper的源码的表面认识



 

原创粉丝点击