android share互联网科技Android开发经验谈

android handler,looper,messageQu

2016-06-16  本文已影响108人  666swb

UI线程

当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread)来负责处理与UI相关的事件,我们叫做UI线程。

为何用handler

简单的说:当主线程队列处理一个消息超过5秒,android 就会抛出一个 ANP(无响应)的异常,所以,我们需要把一些要处理比较长的消息,放在一个单独线程里面处理,把处理以后的结果,返回给主线程运行,就需要用的Handler来进行线程建的通信。

handler简单使用

private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // TODO 接收消息并且去更新UI线程上的控件内容
            if (msg.what == UPDATE) {
                // 更新界面上的textview
                tv.setText(String.valueOf(msg.obj));
            }
            super.handleMessage(msg);
        }
    };
new Thread() {
            @Override
            public void run() {
                // TODO 子线程中通过handler发送消息给handler接收,由handler去更新TextView的值
                try {
                       //do something

                        Message msg = new Message();
                        msg.what = UPDATE;                  
                        msg.obj = "更新后的值" ;
                        handler.sendMessage(msg);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

Handler的handleMessage方法

  1. 向Hanlder的构造函数传入一个Handler.Callback对象,并实现Handler.Callback的handleMessage方法
  1. 无需向Hanlder的构造函数传入Handler.Callback对象,但是需要重写Handler本身的handleMessage方法

Looper简单说明

在主线程申明Handler,有时我们需要继承Thread类实现自己的线程功能,当我们在里面申明Handler的时候会报错。其原因是主线程中已经实现了两个重要的Looper方法

首先looper对象不能为空,就是说loop()方法调用必须在prepare()方法的后面。

Looper一直在不断的从消息队列中通过MessageQueue的next方法获取Message,然后通过代码msg.target.dispatchMessage(msg)让该msg所绑定的Handler(Message.target)执行dispatchMessage方法以实现对Message的处理。

在子线程中简单使用Handler

Handler本质是从当前的线程中获取到Looper来监听和操作MessageQueue,当其他线程执行完成后回调当前线程。
子线程需要先prepare()才能获取到Looper的,是因为在子线程只是一个普通的线程,其ThreadLoacl中没有设置过Looper,所以会抛出异常,而在Looper的prepare()方法中sThreadLocal.set(new Looper())是设置了Looper的。

class Rub implements Runnable {  

        public Handler myHandler;  
        // 实现Runnable接口的线程体 
        @Override  
        public void run() {  

         /*①、调用Looper的prepare()方法为当前线程创建Looper对象并,
          创建Looper对象时,它的构造器会自动的创建相对应的MessageQueue*/
            Looper.prepare();  

            /*.②、创建Handler子类的实例,重写HandleMessage()方法,该方法处理除当前线程以外线程的消息*/
             myHandler = new Handler() {  
                @Override  
                public void handleMessage(Message msg) {  
                    String ms = "";  
                    if (msg.what == 0x777) {  

                    }  
                }  

            };  
            //③、调用Looper的loop()方法来启动Looper让消息队列转动起来
            Looper.loop();  
        }
    }

注意分成三步:

1.调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。

2.有了Looper之后,创建Handler子类实例,重写HanderMessage()方法,该方法负责处理来自于其他线程的消息。

3.调用Looper的looper()方法启动Looper。

然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。

总结:
Handler: **
      发送消息,它能把消息发送给Looper管理的
MessageQueue。 **
      处理消息,并负责处理Looper分给它的消息。
**Message: **
      Handler接收和处理的消息对象。
**Looper: **
      每个线程只有一个Looper,它负责管理对应的MessageQueue,会不断地从MessageQueue取出消息,并将消息分给对应的Hanlder处理。  
      
      主线程中,系统已经初始化了一个Looper对象,因此可以直接创建Handler即可,就可以通过Handler来发送消息、处理消息。 程序自己启动的子线程,程序必须自己创建一个Looper对象,并启动它,调用Looper.prepare()方法。

prapare()方法:保证每个线程最多只有一个Looper对象。

looper()方法:启动Looper,使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给对应的Handler进行处理。

MessageQueue:由Looper负责管理,它采用先进先出的方式来管理Message。

Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。 
  
Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。

源码分析转自地址:http://blog.csdn.net/amazing7/article/details/51424038

上一篇下一篇

猜你喜欢

热点阅读