Handler

来源:互联网 发布:充电数据监控 编辑:程序博客网 时间:2024/06/09 20:12

几个关键概念

MessageQueue

MessageQueue:是一种数据结构,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构
MessageQueue对象不需要我们自己创建。通常使用一个Looper对象对该线程的MessageQueue进行管理。
主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。
其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。
我们可以通过Looper.myQueue()获取当前线程中的MessageQueue。

Message

Message:消息对象,Message Queue中的存放的对象。一个Message Queue中包含多个Message,按照“先进先出”的原则存放消息。
使用Message时,我们可以通过new Message()创建一个Message实例,但是Android更推荐我们通过Message.obtain()或者Handler.obtainMessage()获取Message对象 Message它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。
调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。
使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数

Looper:

Looper: 是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象
创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有Looper对象的。
Looper主要是prepare()和loop()两个方法
prepare() 创建Looper对象和MessageQueue数据结构
loop() 不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
如果想让我们新创建的线程拥有Looper对象时,我们首先应调用Looper.prepare()方法,然后再调用Looper.loop()方法。典型的用法如下:

class LooperThread extends Thread{  public Handler mHandler;  public void run()  {    Looper.prepare();    //其它需要处理的操作    Looper.loop();  }}

Handler

Handler: 消息的处理者。
Message获取:new Message(),或者Message.obtain()或者Handler.obtainMessage()
handler对象的sendMessage(msg)将Message传递给Looper,继而由Looper将Message放入MessageQueue中。
Looper循环查询消息队列MessageQueue,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后就会调用该Message对象对应的handler对象的handleMessage()方法对其进行处理

流程:

1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

Handler的特点

Handler可以分发Message对象(通过sendMessage)和Runnable对象(通过post())到主线程中, 每个Handler实例,都会绑定到创建他的线程中,
它有两个作用:
1 发送消息Message到消息队列中,
2 handleMessage()处理消息
注:post(Runnable)实质也是发送消息Message(Runnable转化成一个Message)到消息队列中,处理是会直接调用run().

post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post类方法允许你发送一个Runnable对象(Runable对象作为callback属性,赋值给了此message,Runnable转化成一个Message)到该创建handle线程的消息队列中。
sendMessage类方法, 允许你发送一个带数据的Message对象到消息队列中.

Handler post

mHandler.post(new Runnable()  {      @Override      public void run()      {          Log.e("TAG", Thread.currentThread().getName());          mTxt.setText("yoxi");      }  });  

然后run方法中可以写更新UI的代码,其实这个Runnable并没有创建新线程,而是发送了一条消息。Runable对象作为callback属性,赋值给了message,Runnable转化成一个Message。
handler会在looper中调用这个Runnable的Run方法执行。
Runnable没有启动(线程的启动是用start()来启动的所以没有创建新线程。

代码参考

private Handler splashHandler = new Handler() {    public void handleMessage(Message msg) {        switch (msg.what) {            case OVER:                progressDialog.dismiss();                break;            default:                break;        }        super.handleMessage(msg);    }}; new Thread() {public void run() {    initList();    Message m = splashHandler.obtainMessage(OVER);    splashHandler.sendMessage(m);    splashHandler.post(r);    splashHandler.postDelayed(r, delayMillis);    splashHandler.postAtTime(r, uptimeMillis);}}.start();//也可以直接使用splashHandler.post(new Runnable(){    public void run() {    //直接跟新        progressDialog.dismiss();    }});//handle+Thread:线程中发送消息,主线程handle处理消息//Handler.post直接在主创建该handler线程中处理

AsyncTask实现的原理和适用的优缺点

AsyncTask,是Android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
使用的优点:
简单,快捷
过程可控
使用的缺点:
在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

Handler异步实现的原理和适用的优缺点

在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)运行并生成Message-Looper获取Message并传递给HandlerHandler逐个获取Looper中的Message,并进行UI变更。
使用的优点:
结构清晰,功能定义明确
对于多个后台任务时,简单,清晰
使用的缺点:
在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

Android的AsyncTask比Handler更轻量级一些(只是代码上轻量一些,而实际上要比handler更耗资源),适用于简单的异步处理。
首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的

0 0
原创粉丝点击