Android开发总结笔记 消息处理机制 5-1

来源:互联网 发布:网络信息员 编辑:程序博客网 时间:2024/05/16 09:48

参考:http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html

Android的消息处理机制有三个核心的类

  • Looper

  • Handler

  • Message

事实上还有另外一个Message Queue消息队列,不过被封装到Looper中了


Looper

Looper用来将一个普通线程变成一个Looper线程


其中用到了两个方法

  • Looper.prepare()

  • Looper.loop()

来看一下源码中这两个方法是怎么运作的。

1)Looper.prepare()

  1.  private Looper(boolean quitAllowed) {
  2.        mQueue = new MessageQueue(quitAllowed);
  3.        mThread = Thread.currentThread();
  4.  }
  5.    public static void prepare() {
  6.        prepare(true);
  7.    }
  8.    private static void prepare(boolean quitAllowed) {
  9.        if (sThreadLocal.get() != null) {
  10.            throw new RuntimeException("Only one Looper may be created per thread");
  11.        }
  12.        sThreadLocal.set(new Looper(quitAllowed));
  13.    }

可以看到内部维护了一个MesssageQueue,这里涉及到了一个变量,ThreadLocal是一个线程的局部变量

  1. static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

这也是为什么一个Thread只能有一个Looper对象的原因。


2)Looper.loop()

  1. public static @Nullable Looper myLooper() {
  2.        return sThreadLocal.get();
  3.    }

可以看到,如果没有执行Looper.prepareme就不会被赋值,从而抛出异常

  1.  public static void loop() {
  2.        final Looper me = myLooper();
  3.        if (me == null) {
  4.            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
  5.        }
  6.        final MessageQueue queue = me.mQueue;
  7.        // Make sure the identity of this thread is that of the local process,
  8.        // and keep track of what that identity token actually is.
  9.        Binder.clearCallingIdentity();
  10.        final long ident = Binder.clearCallingIdentity();
  11.        for (;;) {
  12.            Message msg = queue.next(); // might block
  13.            if (msg == null) {
  14.                // No message indicates that the message queue is quitting.
  15.                return;
  16.            }
  17.            // This must be in a local variable, in case a UI event sets the logger
  18.            Printer logging = me.mLogging;
  19.            if (logging != null) {
  20.                logging.println(">>>>> Dispatching to " + msg.target + " " +
  21.                        msg.callback + ": " + msg.what);
  22.            }
  23.            msg.target.dispatchMessage(msg);
  24.            if (logging != null) {
  25.                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
  26.            }
  27.            // Make sure that during the course of dispatching the
  28.            // identity of the thread wasn't corrupted.
  29.            final long newIdent = Binder.clearCallingIdentity();
  30.            if (ident != newIdent) {
  31.                Log.wtf(TAG, "Thread identity changed from 0x"
  32.                        + Long.toHexString(ident) + " to 0x"
  33.                        + Long.toHexString(newIdent) + " while dispatching to "
  34.                        + msg.target.getClass().getName() + " "
  35.                        + msg.callback + " what=" + msg.what);
  36.            }
  37.            msg.recycleUnchecked();
  38.        }
  39.    }

从第13开始看起,利用一个死循环MessageQuene里面不断地取出Message

24行把真正的处理工作分发给Messagetarget,也就是Handler


Handler

Looper负责从MessageQueue中拿出消息。

那么就需要有一个可以往MessageQueue添加的消息的工具,这个工具就是Handler

除了添加消息之外,Handler还能处理消息,仅限于处理自己发出的消息

先来看看添加消息

  1.   public Handler(Callback callback, boolean async) {
  2.        if (FIND_POTENTIAL_LEAKS) {
  3.            final Class<? extends Handler> klass = getClass();
  4.            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
  5.                    (klass.getModifiers() & Modifier.STATIC) == 0) {
  6.                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
  7.                    klass.getCanonicalName());
  8.            }
  9.        }
  10.        mLooper = Looper.myLooper();
  11.        if (mLooper == null) {
  12.            throw new RuntimeException(
  13.                "Can't create handler inside thread that has not called Looper.prepare()");
  14.        }
  15.        mQueue = mLooper.mQueue;
  16.        mCallback = callback;
  17.        mAsynchronous = async;
  18.    }

11行和16行可以看出,将Looper中的ThreadLocal和消息队列关联到Handler



创建了Handler对象之后,可以利用以上的各种postXXsendXX方法来发送消息到MesssageQueue

可以看到post发出的是Runnable,而send发出的是Message

但是到最后,post发出的Runnable都会被封装成Message

  1.  public final boolean post(Runnable r)
  2.    {
  3.       return  sendMessageDelayed(getPostMessage(r), 0);
  4.    }


  1.  public final boolean sendMessageDelayed(Message msg, long delayMillis)
  2.    {
  3.        if (delayMillis < 0) {
  4.            delayMillis = 0;
  5.        }
  6.        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
  7.    }


下面就是处理消息
在上面的Looper中,有一段

  1. msg.target.dispatchMessage(msg);

这个是Handler的方法,负责处理消息,来看一下这个方法

  1. public void dispatchMessage(Message msg) {
  2.        if (msg.callback != null) {
  3.            handleCallback(msg);
  4.        } else {
  5.            if (mCallback != null) {
  6.                if (mCallback.handleMessage(msg)) {
  7.                    return;
  8.                }
  9.            }
  10.            handleMessage(msg);
  11.        }
  12.    }

可以看到这里调用了接口的方法,让子类去实现

  1.    public interface Callback {
  2.        public boolean handleMessage(Message msg);
  3.    }
  4.    
  5.    /**
  6.     * Subclasses must implement this to receive messages.
  7.     */
  8.    public void handleMessage(Message msg) {

所以,只需要new出一个Handler,并实现handleMessage方法,就可以使用了

  1. private static void handleCallback(Message message) {
  2.        message.callback.run();
  3.    }


Message

Message就是用来携带信息的一类

  1. Message message = Message.obtain();  
  2. message.arg1 = 1;  
  3. message.arg2 = 2;  
  4. message.obj = "Demo";  
  5. message.what = 3;  
  6. Bundle bundleData = new Bundle();  
  7. bundleData.putString("Name", "Lucy");  
  8. message.setData(bundleData);  

Message.obtain用于获取一个Message对象

后面就是一些携带的信息



0 0