• Android的消息处理(Handler相关)


      首先Message(消息)类不用多说,内部用what(啥)属性来存放标识符,用obj(对象)来存放要携带的数据,用target(目标)来存放目标Handler。

      所以需要有一个Handler(句柄)类来处理Message,方法是调用Handler类中的sendMessage(Message)方法,我之前一直觉得这个方法名的逻辑很奇怪,现在懂了,因为知道了另一个类:

      MessageQueue(消息队列),在调用sendMessage之后Handler会依次调用两个不是重载但跟重载也差不多的内部方法,最后像这样

    sent = queue.enqueueMessage(msg, uptimeMillis);

    把Message发送(send)给内部创建的一个MessageQueue对象,同时把Message中的target属性设置为自己。

      这时又要说到另一个类,Looper(循环器)。程序运行的时候安卓会在主线程里创建一个Looper,

     1     /**
     2      * Initialize the current thread as a looper, marking it as an
     3      * application's main looper. The main looper for your application
     4      * is created by the Android environment, so you should never need
     5      * to call this function yourself.  See also: {@link #prepare()}
     6      */
     7     public static void prepareMainLooper() {
     8         prepare(false);
     9         synchronized (Looper.class) {
    10             if (sMainLooper != null) {
    11                 throw new IllegalStateException("The main Looper has already been prepared.");
    12             }
    13             sMainLooper = myLooper();
    14         }
    15     }
    系统调用

    它以for死循环的方式不断尝试从队列中取出Message,

    Message msg = queue.next();

    取到了就调用这个Message中的target中存放的那个Handler的dispatchMessage(Message)方法。像这样:

    msg.target.dispatchMessage(msg);

      Handler用这个方法稍微进行一下判断,之后就转交给自己的handleMessage(Message)方法来处理消息,这个方法和onCreate一样是由程序员重写,由系统调用的。

      剩下的就很简单了,handleMessage方法是程序员自己写的,想做点什么都行。

      通常是根据Message中的what来switch一下,对于不同消息来源做出不同反应就可以啦。


    那么总结一下

      明面上程序员做两件事。

      首先是创建Handler,重写好方法,决定用它来做点什么;

      后面的分为两种情况。

      如果调用Handler的时候需要携带信息,就用Message.obtain()方法或new关键字得到Message对象,然后使用Handler对象的sendMessage(Message)方法交由Handler处理。

      如果并不需要携带额外信息,只需要通知Handler有事要做,就不需要自己得到Message对象,直接使用Handler对象的sendEmptyMessage(int)方法,Handler会像这样

    Message msg = Message.obtain();
    msg.what = what;

    自己创建一个Message对象,并用方法中传入的int值作为Message的what属性。

             第一步,定义Handler。

             第二步,发送消息。

             这样。


    PS:

      如果要在主线程之外使用Handler要注意一个问题。

      首先按照上面说的,消息是由Looper从队列中取出并分发的,只管自己的线程。可是主线程中使用的Looper是安卓系统创建的,用户新建线程的时候并不会自动创建一个新的Looper,所以Looper告诉你

    final Looper me = myLooper();
    if (me == null) {
         throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }

    这个,Handler告诉你

    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }

    这个。

      因此,要在新线程里创建Handler就需要调用Looper.prepare()方法来准备好一个Looper,这个方法会自动调用内部的重载方法,不需要担心。

        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));
        }

      自己调用的时候参数是true,系统调用的时候是false,总之不需要在意。

      Handler用来让其他线程修改UI啊,这个不用我说吧。

  • 相关阅读:
    PVID和VID与交换机端口
    IO密集型和CPU密集型区别?
    Redis回收进程是如何工作的
    索引的工作原理及其种类
    drop,delete与truncate的区别
    你用过的爬虫框架或者模块有哪些?优缺点?
    列举您使用过的Python网络爬虫所用到的网络数据包
    对cookies与session的了解?他们能单独用吗
    有用过Django REST framework吗
    Django中哪里用到了线程?哪里用到了协程?哪里用到了进程
  • 原文地址:https://www.cnblogs.com/chihane/p/3952400.html
Copyright © 2020-2023  润新知