Android中Handler详解
2016-07-01 20:41
411 查看
Handler在Android中有着重要的作用,学习Handler能清晰的理解Android线程消息传递机制。
Handler重要有两个应用场景:
1.安排一个消息或者runnable在未来的某个时间点执行
2.在其他线程执行你的方法
消息队列完成的方法包括
1. post(Runnable)
2. postAtTime(Runnable, long)
3. postDelayed(Runnable, long)
4. sendEmptyMessage(int)
5. sendMessage(Message)
6. sendMessageAtTime(Message, long)
7. sendMessageDelayed(Message, long)
这里包含post的允许你传入一个runnable对象进入队列而被消息队列唤起,而sendMessage允许你把一个消息传入队列,这个消息包含绑定的数据,这个消息将会被handlerMessage(Message)所处理。
当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread)来负责处理与UI相关的事件,我们叫做UI线程。
Android的UI操作并不是线程安全的(出于性能优化考虑),意味着如果多个线程并发操作UI线程,可能导致线程安全问题。
为了解决Android应用多线程问题—Android平台只允许UI线程修改Activity里的UI组建,就会导致新启动的线程无法改变界面组建的属性值。
子线程处理完成任务后发送消息到上面:
1.public Handler()
2.public Handler(Callbackcallback)
3.public Handler(Looperlooper)
4.public Handler(Looperlooper, Callbackcallback)
第1个和第2个构造函数都没有传递Looper,但源码注释中说了(Default constructor associates this handler with the {@link Looper} for the current thread.)就是说这两个构造函数都将通过调用Looper.myLooper()获取当前线程绑定的Looper对象,然后将该Looper对象保存到名为mLooper的成员字段中。
后两个构造方法则将Looper赋值到mlooper中
这里的Handler消息传递的整体图为:
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
或者
什么是Handler?
Android官方文档给出的解释是:一个Handler允许你发送和处理Message和与某一线程相关联的Runnable对象。每一个Handler实例都与一个单一的线程和他的消息队列相关联。当你创建了一个新的Handler,这个Handler就绑定到了这个线程或者消息队列,将会分发这个消息和runnable到消息队列中,并在他们出队列的时候执行。Handler重要有两个应用场景:
1.安排一个消息或者runnable在未来的某个时间点执行
2.在其他线程执行你的方法
消息队列完成的方法包括
1. post(Runnable)
2. postAtTime(Runnable, long)
3. postDelayed(Runnable, long)
4. sendEmptyMessage(int)
5. sendMessage(Message)
6. sendMessageAtTime(Message, long)
7. sendMessageDelayed(Message, long)
这里包含post的允许你传入一个runnable对象进入队列而被消息队列唤起,而sendMessage允许你把一个消息传入队列,这个消息包含绑定的数据,这个消息将会被handlerMessage(Message)所处理。
Handler的应用背景
上面大致讲了一下Handler在官方文档上的描述,下面讲一下Handler的应用背景。当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread)来负责处理与UI相关的事件,我们叫做UI线程。
Android的UI操作并不是线程安全的(出于性能优化考虑),意味着如果多个线程并发操作UI线程,可能导致线程安全问题。
为了解决Android应用多线程问题—Android平台只允许UI线程修改Activity里的UI组建,就会导致新启动的线程无法改变界面组建的属性值。
Handler更新UI的方法
1.在主线程中声明: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源码分析
Handler中主要有四个构造函数:1.public Handler()
2.public Handler(Callbackcallback)
3.public Handler(Looperlooper)
4.public Handler(Looperlooper, Callbackcallback)
第1个和第2个构造函数都没有传递Looper,但源码注释中说了(Default constructor associates this handler with the {@link Looper} for the current thread.)就是说这两个构造函数都将通过调用Looper.myLooper()获取当前线程绑定的Looper对象,然后将该Looper对象保存到名为mLooper的成员字段中。
final Looper mLooper; public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
后两个构造方法则将Looper赋值到mlooper中
public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
这里的Handler消息传递的整体图为:
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
在Android开发中主要的使用方法
1在主线程中定义Handler
Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: String data = (String)msg.obj; updateUI(); textView.setText(data); break; default: break; } } };
private void update() { new Thread(new Runnable(){ @Override public void run() { //耗时操作,完成之后发送消息给Handler,完成UI更新; //需要数据传递,用下面方法; Message msg =new Message(); msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等; mHandler.sendMessage(msg); } }).start(); }
2 用Activity对象的runOnUiThread方法更新
new Thread() { public void run() { //这儿是耗时操作,完成之后更新UI; runOnUiThread(new Runnable(){ @Override public void run() { //更新UI imageView.setImageBitmap(bitmap); } }); } }.start();
或者
Activity activity = (Activity) imageView.getContext(); activity.runOnUiThread(new Runnable(){ @Override public void run() { imageView.setImageBitmap(bitmap); } });
3View.post(Runnable r)
imageView.post(new Runnable(){ @Override public void run() { imageView.setImageBitmap(bitmap); } });
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories