Android中Handler的运行机制

前言

Handler是Android提供给开发者用于进行异步消息处理的类,当我们需要在子线程处理耗时的操作(如数据读写,网络操作等),当耗时的操作完成后,需要更新UI界面,这时就需要使用Handler消息机制来处理。

Handler机制原理

Handler消息机制是由Handler、Message、MessageQueue以及Looper对象组成。搞清楚它们之间的关系,Android开发中的Handler消息处理机制也掌握了个大概了。

Handler

Handler是线程间消息发送和接收的即时接口,每个Handler都有一个与之关联的Looper和消息队列。

Handler的几个常见的构造方法:

Handler() 默认构造方法,与当前线程及其Looper实例绑定。如在主线程中执行new Handler(),那么该handler实例所绑定的便是 UI 线程和 UI 线程绑定的Looper实例。

Handler(Handler.Callback callback) 与当前线程及其Looper实例绑定,同时调用一个callback接口(用于实现消息处理——即在callback中重写handleMessage()方法)

-Handler(Looper looper) 将该新建的handler实例与指定的looper对象绑定。

Handler(Looper looper, Handler.Callback callback) 

指定该handler实例所绑定的looper实例并使用给定的回调接口进行消息处理。

而这些构造函数最终调用的其实都是下面这个构造方法,只是参数缺少的自动补为null或false而已。

public Handler(Looper looper, Callback callback, booleanasync) { 

        mLooper = looper;

        mQueue = looper.mQueue;

        mCallback = callback; 

        mAsynchronous =async;

}

Handler的作用,它允许我们将Message或Runnable对象发送到当前线程绑定的MessageQueue中,并通过Looper对象不断循环地从队列中获取Message或Runnable对象进行处理。因此,Handler有两个主要的用途:

定时执行messages 和 runnables;

在将一个action入队并在其他线程中执行;

在第一个用途中,有以下几个方法可以用:

post(Runnable):将runnable对象入队。

public final boolean post(Runnable r){

        return sendMessageDelayed(getPostMessage(r),0);

}

postAtTime(Runnable, long):将runnable对象入队,并在指定时间执行

public final boolean postAtTime(Runnable r,longuptimeMillis){

          return sendMessageAtTime(getPostMessage(r), uptimeMillis);

}

postDelayed(Runnable, long):将runnable对象入队,并经过指定时间后执行。

public final boolean postDelayed(Runnable r,longdelayMillis){

           return sendMessageDelayed(getPostMessage(r), delayMillis);

}

sendEmptyMessage(int):发送只具有what标志值得message。

public final boolean sendEmptyMessage(intwhat){

return sendEmptyMessageDelayed(what,0);

}

public final boolean sendEmptyMessageDelayed(intwhat,longdelayMillis) { 

   Message msg = Message.obtain(); 

   msg.what = what;

   return sendMessageDelayed(msg, delayMillis);

}

sendMessage(Message):将一个message对象入队,且允许该message对象带有一些数据,如一个bundle类型的数据或一个int类型的标志值等,这些数据将在Handler的handleMessage(Message) 方法中进行处理,当然,具体处理逻辑需要我们自己重写handleMessage()方法。

public final boolean sendMessage(Message msg){

      return sendMessageDelayed(msg,0);

}

sendMessageDelayed(Message, long):将message入队,并在当前时间延迟指定时间长度前将该消息放在所有挂起的消息之后。

public final boolean sendMessageDelayed(Message msg,longdelayMillis){

        if(delayMillis <0) {  

            delayMillis =0;    

        }

        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

}


Message

Message: 一个message包含描述和任意数据对象的消息,用于发送给Handler。

//获取Message实例的方式Messagemsg1 =Message.obtain();//或Messagemsg2 = Handler.obtainMessage();

虽然Message的构造方法是public的,但实例化Message的最好方法是调用Message.obtain() 或 Handler.obtainMessage() ,因为这两个方法是从一个可回收利用的message对象回收池中获取Message实例。该回收池用于将每次交给handler处理的message对象进行回收。 

 Message对象包含两个额外的int类型变量和一个额外的对象,利用它们大多数情况下我们不用再做内存分配相关工作。实例化Message最好的方法是调用Message.obtain()或Handler.obtainMessage()(实际上最终调用的仍然是Message.obtain()),因为这两个方法都是从一个可回收利用的对象池中获取Message的。

MessageQueue

MessageQueue:消息队列。内部存储着一组消息。对外提供了插入和删除的操作。MessageQueue内部是以单链表的数据结构来存储消息列表的。

获取MessageQueue实例使用Looper.myQueue()方法。

查看源码中的enqueueMessage()方法能看出MessageQueue是用单链表的数据结构来存储消息的。

//插入Message操作

boolean enqueueMessage(Message msg,longwhen){

if(msg.target ==null) {

thrownewIllegalArgumentException("Message must have a target.");

}

if(msg.isInUse()) {

thrownewIllegalStateException(msg +" This message is already in use.");       

}     

synchronized (this) {

if(mQuitting) { 

IllegalStateException e =newIllegalStateException(msg.target +" sending message to a Handler on a dead thread");

Log.w(TAG, e.getMessage(), e); 

msg.recycle();returnfalse; 

}         

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(;;) {

//从这里可看出MessageQueue内部是以单链表的数据结构来存储消息的

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; 

}


Looper

Looper:主要用于给一个线程轮询消息的。线程默认没有Looper,在创建Handler对象前,我们需要为线程创建Looper。

使用Looper.prepare()方法创建Looper,使用Looper.loop()方法运行消息队列。

classLooperThreadextendsThread{ 

       publicHandlermHandler;  

        public void run() {

        Looper.prepare();       

       mHandler =newHandler() {      

          public void handleMessage(Messagemsg) {

            // process incoming messages here

        }           

 };

Looper.loop();   

}

有个疑问,我们在主线程中,创建Handler之前并没有创建Looper。这是为什么呢?查看Main Thread源码(也就是ActivityThread),实际上是在ActivityThread主线程启动时Looper有被初始化创建。

public static void main(String[] args){

        ...

        //初始化Looper        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");

    }

}

你可能感兴趣的:(Android中Handler的运行机制)