zoukankan      html  css  js  c++  java
  • Android线程Handler的学习

    Android的UI是单线程(Single-threaded)的。为了避免拖住GUI,一些较费时的对象应该交给独立的线程去执行。如果幕后的线程来执行UI对象,Android就会发出错误讯息 CalledFromWrongThreadException

    Message Queue

         在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:

     

    1. Message
        Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
     
    2. Handler
        Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的Handler对象引用来 sendMes sage(Message) 。而使用Handler,需要implement 该类的   handleMessage(Message) 方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。
     
    3. Message Queue
        Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
        每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
     
    4. Looper
        Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。

        对于子线程使用Looper,API Doc提供了正确的使用方法:

    class LooperThread extends Thread { 
        public Handler mHandler; 
     
        public void run() { 
            Looper.prepare(); //创建本线程的Looper并创建一个MessageQueue
     
            mHandler = new Handler() { 
                public void handleMessage(Message msg) { 
                    // process incoming messages here 
                } 
            }; 
       
            Looper.loop(); //开始运行Looper,监听Message Queue 
        } 
    } 


    这个Message机制的大概流程:

        1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。

        2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用该Message的target指向的Hander的dispatchMessage函数对Message进行处理。

        在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:

        1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;

        2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;

        3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。

        由此可见,我们实现的handleMessage方法是优先级最低的!

        3. Handler处理完该Message (update UI) 后,Looper则设置该Message为NULL,以便回收!


  • 相关阅读:
    关于Java8:StreamAPI的一点记录
    关于JDBC的批量操作executeBatch()所引发sql语句异常
    [Java]直播方案----[接入环信聊天室]+[腾讯云直播]
    获取SpringCloud gateway响应的response的值,记录踩坑
    Spring Boot2.1.7启动zipkin-server报错:Error creating bean with name 'armeriaServer' defined in class path
    java.lang.IllegalArgumentException: Prometheus requires that all meters with the same name have the same set of tag keys.
    Spring Cloud Gateway报错:Unable to start embedded Tomcat
    poi设置Word页边距
    访问rabbitmq-server失败
    RabbitMQ获取队列的消息数目
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3024927.html
Copyright © 2011-2022 走看看