Android消息处理机制
2015-11-03 14:39
344 查看
学习Android的消息处理机制,有几个概念(类)必须了解:
1.Message 消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。
2.Message Queue 消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
3.Handler Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。
4.Looper 循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。
5.线程 UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。 每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。
运行机理:
每个线程都可以并仅可以拥有一个Looper实例,消息队列MessageQueue在Looper的构造函数中被创建并且作为成员变量被保存,也就是说MessageQueue相对于线程也是唯一的。Android应用在启动的时候会默认会为主线程创建一个Looper实例,并借助相关的Handler和Looper里面的MessageQueue完成对Activities、Services、Broadcase
Receivers等的管理。而在子线程中,Looper需要通过显式调用Looper.
Prepare()方法进行创建。Prepare方法通过ThreadLocal来保证Looper在线程内的唯一性,如果Looper在线程内已经被创建并且尝试再度创建”Only
one Looper may be created per thread”异常将被抛出。
Handler在创建的时候可以指定Looper,这样通过Handler的sendMessage()方法发送出去的消息就会添加到指定Looper里面的MessageQueue里面去。在不指定Looper的情况下,Handler绑定的是创建它的线程的Looper。如果这个线程的Looper不存在,程序将抛出”Can’t
create handler inside thread that has not called Looper.prepare()”。
整个消息处理的大概流程是:1. 包装Message对象(指定Handler、回调函数和携带数据等);2.
通过Handler的sendMessage()等类似方法将Message发送出去;3.
在Handler的处理方法里面将Message添加到Handler绑定的Looper的MessageQueue;4.
Looper的loop()方法通过循环不断从MessageQueue里面提取Message进行处理,并移除处理完毕的Message;5.
通过调用Message绑定的Handler对象的dispatchMessage()方法完成对消息的处理。
在dispatchMessage()方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:1.
Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;2.
Handler里面mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;3.
处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
1.上面说的handler是一个关键的组件,它关联一个Looper,关联一个msg,还有它自己的的处理方法。把处理消息的三个要素全部结合在一起了,运行的线程、处理的方法、处理的数据,三个要素可以灵活配置。
如果handler与Looper没有关系,那么这个handler可以理解成一个函数对象,带着操作,带着数据,就是等待线程func()执行它。这里把“函数对象”(或者理解为命令模式中的一个command)如何放入指定的Looper给封装起来,并且把消息队列也给封装了起来,使用的时候就很方便了。
一段使用的例子如下:
上面的更新操作较简单。如果界面更新线程是单线程(也应该是单线程)那么,在更新界面操作中不需要加锁。而且在一般的线程通信时候,如果线程之间都是handler通过发送msg的方式传递消息,那么大多数操作也是不用加锁的。需要加锁的地方很多都已经封装起来了,例如mHandler.sendMessage时候向消息队列传递消息和从消息队列中获取消息的过程。
2.Android框架还规定了更新ui必须在ui线程中,这种做法不仅安全,而且高效。一般界面框架都有专门单独的更新ui的线程,但要特别注意,更新操作一般是阻塞的不要处理耗时过长的操作。
/content/3806637.html
1.Message 消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。
2.Message Queue 消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
3.Handler Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。
4.Looper 循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。
5.线程 UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。 每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。
运行机理:
每个线程都可以并仅可以拥有一个Looper实例,消息队列MessageQueue在Looper的构造函数中被创建并且作为成员变量被保存,也就是说MessageQueue相对于线程也是唯一的。Android应用在启动的时候会默认会为主线程创建一个Looper实例,并借助相关的Handler和Looper里面的MessageQueue完成对Activities、Services、Broadcase
Receivers等的管理。而在子线程中,Looper需要通过显式调用Looper.
Prepare()方法进行创建。Prepare方法通过ThreadLocal来保证Looper在线程内的唯一性,如果Looper在线程内已经被创建并且尝试再度创建”Only
one Looper may be created per thread”异常将被抛出。
Handler在创建的时候可以指定Looper,这样通过Handler的sendMessage()方法发送出去的消息就会添加到指定Looper里面的MessageQueue里面去。在不指定Looper的情况下,Handler绑定的是创建它的线程的Looper。如果这个线程的Looper不存在,程序将抛出”Can’t
create handler inside thread that has not called Looper.prepare()”。
整个消息处理的大概流程是:1. 包装Message对象(指定Handler、回调函数和携带数据等);2.
通过Handler的sendMessage()等类似方法将Message发送出去;3.
在Handler的处理方法里面将Message添加到Handler绑定的Looper的MessageQueue;4.
Looper的loop()方法通过循环不断从MessageQueue里面提取Message进行处理,并移除处理完毕的Message;5.
通过调用Message绑定的Handler对象的dispatchMessage()方法完成对消息的处理。
在dispatchMessage()方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:1.
Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;2.
Handler里面mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;3.
处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
1.上面说的handler是一个关键的组件,它关联一个Looper,关联一个msg,还有它自己的的处理方法。把处理消息的三个要素全部结合在一起了,运行的线程、处理的方法、处理的数据,三个要素可以灵活配置。
如果handler与Looper没有关系,那么这个handler可以理解成一个函数对象,带着操作,带着数据,就是等待线程func()执行它。这里把“函数对象”(或者理解为命令模式中的一个command)如何放入指定的Looper给封装起来,并且把消息队列也给封装了起来,使用的时候就很方便了。
一段使用的例子如下:
Looper looper = Looper.myLooper();//取得当前线程里的looper MyHandler mHandler =new MyHandler(looper);//构造一个handler使之可与looper通信 //buton等组件可以由mHandler将消息传给looper后,再放入messageQueue中,同时mHandler也可以接受来自looper消息 mHandler.removeMessages(0); String msgStr ="主线程不同组件通信:消息来自button"; Message m = mHandler.obtainMessage(1, 1, 1, msgStr);//构造要传递的消息 mHandler.sendMessage(m);//发送消息:系统会自动调用handleMessage方法来处理消息 privateclass MyHandlerextends Handler{ public MyHandler(Looper looper){ super(looper); } @Override publicvoid handleMessage(Message msg) {//处理消息 text.setText(msg.obj.toString()); } }
上面的更新操作较简单。如果界面更新线程是单线程(也应该是单线程)那么,在更新界面操作中不需要加锁。而且在一般的线程通信时候,如果线程之间都是handler通过发送msg的方式传递消息,那么大多数操作也是不用加锁的。需要加锁的地方很多都已经封装起来了,例如mHandler.sendMessage时候向消息队列传递消息和从消息队列中获取消息的过程。
2.Android框架还规定了更新ui必须在ui线程中,这种做法不仅安全,而且高效。一般界面框架都有专门单独的更新ui的线程,但要特别注意,更新操作一般是阻塞的不要处理耗时过长的操作。
/content/3806637.html
相关文章推荐
- android 动态添加ImageView 设置setPadding不起作用问
- Android AsyncTask异步的学习
- Android中监听ListView滑动到底部
- android color.xml
- [Android基础]Service
- 【Android开发精要笔记】Android的Intent机制
- Android BitmapShader 实战 实现圆形、圆角图片
- Android签名简介
- Android 桌面悬浮窗进阶,QQ手机管家小火箭效果实现
- Android Error: android.os.NetworkOnMainThreadException
- Android学习—计算器实现
- Ubuntu(64bit)搭建Android测试环境
- 安卓开发学习之015 ImageView(一)基础属性详解
- Android 开发 --Unable to resolve target 'android-19'
- 黑马52期+28期+32期+46期最新android视频免费下载
- Android Facebook登录的简单实现
- PopupWindow实现android自定义弹出框口
- Android字符串转化方法
- 基于chromium for android开发Android浏览器
- android linearlayout 的gravity属性