学习Handler,Message,MessageQueue,Thread,Looper之间的关系

最近又复习了Handler,Message,MessageQueue,Thread,Looper,记录一下。
Looper类

 Looper类在消息机制中扮演着消息循环的角色,默认的线程没有与之相关的消息循环,创建消息循环,需要在线程中调用Looper类的prepare()方法创建,然后调用loop()方法让它循环处理消息。

Looper类的构造函数源码:

<span style="font-size:14px;">private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }</span><span style="font-size: 12px;">
</span>

在Looper的构造方法中创建了一个MessageQueue即消息队列,然后将消息队列mQueue和当前线程对象mThread保存起来。

一个典型的例子,使用prepare()和loop()分离来创建一个初始的Handler来与Looper交互。

class LooperThread extends Thread {
      public Handler mHandler;

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

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }


loop()方法源码:

<span style="font-size:14px;"> 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 (;;) {
           <strong> 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();
        }
    }</span>

Looper类的loop方法的工作过程:

首先调用Looper类的myLooper方法获取Looper对象me;

然后me.mQueue获取消息队列queue;

loop方法是一个死循环,通过MessageQueue的next方法来获取新消息msg,如果MessageQueue的next方法返回了null,那么消息队列退出。MessageQueue的next是一个阻塞操作,当没有消息时,next方法会一直阻塞在那里,如果MessageQueue返回了新消息,则会调用msg.target.dispatchMessage(msg),这里的msg.target是一发送这条消息的Handler对象,这样Handler发送的消息最终又交给它的dispatchMessage方法处理了。


Looper类常用方法:

public static void prepare ()  //初始化当前线程作为一个Looper,这给你机会创建handlers,然后引用这个looper,调用loop()启动循环,调用quit()结束循环。

public static void loop ()     //运行线程的消息队列,一定要调用quit()方法结束循环;
public static Looper getMainLooper ()   //返回应用程序的main looper,存在于应用程序的主线程。
public MessageQueue getQueue ()        //获取循环的消息队列

public Thread getThread ()      //获取与Looper相关的线程
public boolean isCurrentThread ()    //如果当前线程是这个looper的线程返回true

public static Looper myLooper ()  //返回与当前线程相关的Looper对象,如果调用Looper.loop()的线程与Looper不相关返回null。
public static MessageQueue myQueue ()    //返回与当前线程关联的消息队列,这必须从一个线程中被调用来运行一个Looper,否则抛出空指针异常。
总结:

Looper的创建在线程内,Looper内部保存消息队列和当前线程

创建并启动消息循环,通过调用Looper的两个静态方法prepare()和loop()。

类。

Handler类

位于android.os.Handler包

Handler发送和处理与一个线程的消息队列关联的Message和Runnable对象。每个Handler实例与一个线程和消息队列关联。当你创建一个新的Handler时,它发送messages和runnables到消息队列,当messages和runnables从消息队列中取出来,由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 使用以下方法:

post(Runnable),

postAtTime(Runnable, long),

postDelayed(Runnable, long),

sendEmptyMessage(int),  

sendMessage(Message),

sendMessageAtTime(Message, long),

 sendMessageDelayed(Message, long) 

Thepost 版本允许你排队 Runnable 对象,这些对象将由消息队列调用; 

the sendMessage版本允许你排队 Message 对象,Message对象包含书,将由Handler的handleMessage(Message) 方法处理。(r要求你实现一个Handler的子类).

当发送Runnable或Message给一个Handler时, 你可以允许消息队列立即开始处理或者延迟处理,允许你实现超时,时间间隔或其他计时行为。

当应用程序的一个进程被创建时,它的主线程致力于运行一个消息队列,这个消息队列负责管理顶级应用程序对象 (activities, broadcast receivers, etc) and any windows they create. 你可以创建自己的线程,并且通过Handler与主应用程序线程交互。 这通过在你自己新创建的线程中调用post orsendMessage方法,  Runnable or Message 然后将被在Handler的消息队列中排队,合适时机处理。 

Handler类常用方法有:

public void dispatchMessage(Message msg)  //处理系统消息
public void handleMessage(Message msg)  //子类必须实现这个方法来接收消息
public final Looper getLooper ()
public final Message obtainMessage ()  //从全局消息池中返回一个新消息对象,比创建和分配新实例更有效。获得的消息实例有对应的Handler,如果
public final Message obtainMessage (int what, int arg1, int arg2)  //与obtainMessage()除了设置了what,arg1,arg2参数外,用法几乎相同。
还有其他obtainMessage方法,不一一列举了。可以参考官方API文档。

Handler构造方法
publicHandler()  //默认构造函数,将handler与当前线程的Looper连接,如果线程没有looper,这个handler不能接收消息,将抛出异常。
publicHandler(Handler.Callback callback)  
publicHandler(Looper looper)  //
publicHandler(Looper looper,Handler.Callback callback)
public Handler (Callback callback, boolean async)

查看源码之后发现Handler(), Handler(Handler.Callback callback)这两个构造函数调用的是Handler(Callback callback, boolean async)这个构造函数,那么看一下它的源码:
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;
    }

从上面源码可以看出,mLooper = Looper.myLooper(); Handler内部获取当前线程的Looper对象mLooper,如果mLooper为null,那么将抛出运行时异常“Can't create handler inside thread that has not called Looper.prepare()。

android开发艺术探索P374中描述了Handler的工作原理:Handler的创建时会采用当前线程的Looper来构建内部的消息循环系统,如果当前线程没有Looper,那么就会报错。


Handler类方法源码:
Handler->handleCallBack(Message message)   调用的是Message对象的message.callback.run();
private static void handleCallback(Message message) {
        message.callback.run();
    }
  Handler -> hasCallbacks(Runnable r)     调用的是MessageQueue的hasMessages方法
 public final boolean hasCallbacks(Runnable r) {
        return mQueue.hasMessages(this, r, null);
    }
Handler-> removeMessages方法调用的是MessageQueue的removeMessages方法
public final void removeMessages(int what) {
        mQueue.removeMessages(this, what, null);

总结:
Handler的创建需要在创建了Looper的线程中;
android的主线程是ActivityThread,主线程的入口方法为main,在main方法中系统通过Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue,并通过Looper.loop()开启消息循环,所以可以在主线程中创建Handler对象。
Handler的创建和Looper和MessageQueue没有直接的关系,Handler是在Thread中创建,如果Thread中创建并运行了Looper,那么Handler可以处理Looper关联的消息队列中的消息。

Message消息类
target  是发送此Message的Handler对象;
Handler中维护这一个MessageQueue对象;
常用方法:
public void sendToTarget();  // 发送Message给由getTarget()方法指定的Handler;
public static Message obtain (Handler h);   //从整个消息池中返回一个新的Message实例,避免重新分配新的对象,从而减少内存的开销。
public static Message obtain (Handler h, int what);
public static Message obtain (Handler h, int what, Object obj);
public void setData (Bundle data);
public void sendToTarget (); //发送Message到与此相关的Handler对象

Message使用实例代码:
Message msg = handler.obtainMessage();
msg.what = LOCAT_ERROR;
msg.obj = message;
msg.sendToTarget();
其中:
what 用户定义的消息代码,以便接收者可以识别消息是什么。
obj 发送给接收者的任意对象。

MessageQueue消息队列
MessageQueue与Thread,Handler没有直接关联,它是在Looper的构造方法中创建并保存,可以通过Looper构造函数的源码查看到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值