• Android之MessageQueue、Looper、Handler与消息循环


    在android的activity中有各种各样的事件,而这些事件最终是转换为消息来处理的。android中的消息系统涉及到:
     *  消息发送
     *  消息队列
     *  消息循环
     *  消息分发
     *  消息读取
      消息对应的重要类有MessageQueue、Looper、Handler,它们分别对应着消息队列、消息循环和消息处理。

     

    Handler类:
    Handler主要用来发送消息和处理消息。每个handler实例都对应着一个线程和该线程的消息队列。
    当你创建一个handler对象时,该handler对象就属于创建它的线程,并和该线程的消息队列绑定,比如在主线程中创建handler对象,那么该handler就只属于主线程,并且和主线程的消息队列绑定。(当然,每个线程都有自己的消息队列,在android中,消息队列是针对与线程的)。这样,该handler就可以发送消息到该消息队列并且处理该消息队列的消息了。
    当执行一些费时的操作时,比如需要远程网络访问、下载等操作时,一般情况下都会启动一个新的线程去操作。而不会放在ui线程去做,这样可以防止android的5秒无相应导致的ANR异常。子线程中返回的结果怎样更新到ui线程呢,这时就可以通过handler来处理了。可以在主线程中定义handler,然后通过主线程handler把子线程中的消息发送到主线程对应的消息队列。在主线程中通过handler.handlerMessage就可以处理消息了,并更新到ui了。
    我们刚才说过,Handler主要是用来发送、处理消息的。那么消息循环、队列是在哪里管理的。答案是:Looper、MessageQueue中。

    Looper类:
    looper类主要用来开启线程的消息循环。默认情况下,系统在启动的时候会为主线程创建消息循环。其他新创建的线程则没有,
    如果需要,可以在该线程内调用Looper.prepare()来启用looper对象,然后调用Looper.loop()进入消息循环。
    这样该线程就具有消息循环机制了,比如:

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

    实际上消息队列也是在Looper中创建的,看下Looper的loop()方法,这个方法就是用来做消息循环用的。

    public static final void loop() {  
             Looper me = myLooper(); //获得当前线程的Looper对象  
             MessageQueue queue = me.mQueue;  //获得当前线程的消息队列  
            while (true) { //条件为true、一直循环执行。消息循环  
                Message msg = queue.next(); // might block  
                  //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.whclearForRecycleat  
                             );  
                     msg.target.dispatchMessage(msg); //消息分发  
                    if (me.mLogging!= null) me.mLogging.println(  
                             "<<<<< Finished to    " + msg.target + " "  
                             + msg.callback);  
                     msg.recycle(); //消息已经分发出去,对消息进行回收处理  
                 }  
             }  
         }  

    我们再来看Handler的构造函数,在Handler的构造函数中获得当前线程的Looper对象、和消息队列。消息队列也是从looper中获得的,刚才我们说过。

    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());  
                 }  
             }   
              //在Handler的构造函数中获得当前线程的Looper对象、和消息队列。消息队列也是从looper中获得的  
             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 = null;  
         }  

    在handler中还有一些重要的方法:

     

    handleMessage(Message)   //处理消息

    dispatchMessage(Message)  //分发消息

    sendMessage(Message)   //发送消息

     

    到这里我们大致可以了解android中的消息流程大概是这样的:
    Handler获得当前线程的Looper、MessageQueue,并且发送消息到MessageQueue中。 Looper对消息做循环,并通过 msg.target.dispatchMessage来分发消息(target应该就是handler)。然后Handler.handlerMessage处理消息。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    android136 360 拖拽
    android134 360 07 归属地查询
    android133 360 06 一键锁频,清楚数据
    转载:必须收藏!50个最流行的免费Kubernetes工具集
    SQL Data Compare 对比 SQLserver数据
    PLSQL 使用ODBC 数据源导入来自SQLSERVER的数据
    PLSQL 使用技巧汇总贴(一个坑)
    简单的数据库备份语句--Oracle+SQLSERVER
    SQLSERVER 导出表数据为insert 语句
    Oracle 使用PLSQL 导出 一个表的insert 语句
  • 原文地址:https://www.cnblogs.com/androidsj/p/3142190.html
Copyright © 2020-2023  润新知