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的更新只能在主线程中完成,因此异步处理是不可避免的
- Handler
- Handler
- Handler
- handler
- handler
- Handler
- Handler
- Handler
- Handler
- Handler
- Handler
- handler
- Handler
- handler
- handler
- Handler
- Handler
- Handler
- tomcat环境下服务器文件句柄耗尽(Too Many Open Files)的问题排查
- Html中 visibility:hidden 与 display:none 的区别
- unix学习---unix系统常用命令集锦
- DirectCompute tutorial for Unity: Kernels and thread groups
- c# XML和实体类之间相互转换(序列化和反序列化)
- Handler
- python03-list_tuple_dict_set
- CentOS 6安裝VNC、Xfce桌面
- heapsort实现代码
- 文章标题
- 信号量 与共享内存
- Androidstudio中自定义字体
- BestCoder #83 1003 zxa and leaf(二分查找/BFS)
- Windows系统搭建Mysql Cluster集群