Handler之消息循环
Handler是用于操作线程内部的消息队列的类。这有点绕,没关系,我们慢慢的来讲。前面Looper一篇讲到了Looper是用于给线程创建消息队列用的,也就是说Looper可以让消息队列(MessageQueue)附属在线程之内,并让消息队列循环起来,接收并处理消息。但,我们并不直接的操作消息队列,而是用Handler来操作消息队列,给消息队列发送消息,和从消息队列中取出消息并处理。这就是Handler的职责。
Handler,Looper和MessageQueue是属于一个线程内部的数据,但是它提供给外部线程访问的接口,Handler就是公开给外部线程,与线程通讯的接口。换句话说,这三个东西都是用来线程间通讯用的(ITC--Inter Thread Communication),与进行间通讯(IPC--Inter Process Communication)的消息队列msgque的核心思想是一致的。MessageQueue是相对较底层的,较少直接使用,Looper和Handler就是专门用来操作底层MessageQueue的。
还有一个重要的数据结构是通讯的基本元素,就是消息对象(Message),Message从来不单独使用,它都是跟随Handler来使用的。具体方法可以参考文档,但需要注意的是同一个消息对象不能发送二次,否则会有AndroidRuntimeException: { what=1000 when=-15ms obj=.. } This message is already in use."。每次发送消息前都要通过Message.obtain()来获取新的对象,或者,对于不需要传送额外数据的直接发送空消息就好Handler.sendEmptyMessage(int)。另外也需要注意消息对象是不能手动回收的,也就是说你不能调用Message.recycle()来释放一个消息对象,因为当该对象被从队列中取出处理完毕后,MessageQueue内部会自动的去做recycle()。这个理解起来也很容易,因为发送一个消息到消息队列后,消息什么时候会被处理,对于应用程序来讲是不知道的,只有MessageQueue才会知道,所以只能由MessageQueue来做回收释放的动作。
因为Handler是用于操作一个线程内部的消息队列的,所以Handler必须依附于一个线程,而且只能是一个线程。换句话说,你必须在一个线程内创建Handler,同时指定Handler的回调handlerMessage(Message msg)。
Handler主要有二个用途,一个是用于线程内部消息循环; 另外一个就是用于线程间通讯。
Handler的基本用法可以参考文档,说的还是比较清楚的。
用于线程内部消息循环
主要是用作在将来定时做某个动作,或者循环性,周期性的做某个动作。主要的接口就是
- Handler.sendEmptyMessageDelayed(int msgid, long after);
- Handler.sendMessageDelayed(Message msg, long after);
- Handler.postDelayed(Runnable task, long after);
- Handler.sendMessageAtTime(Message msg, long timeMillis);
- Handler.sendEmptyMessageAtTime(int id, long timeMiilis);
- Handler.postAtTime(Runnable task, long timeMillis);
这些方法的目的都是设置一个定时器,在指定的时间后,或者在指定的时间向Handler所在的MessageQueue发送消息。这样就非常方便应用程序实现定时操作,或者循环时序操作(处理消息时再延时发送消息,以达成循环时序)。
这个使用起来并不难,但需要注意一点的是,线程内部消息循环并不是并发处理,也就是所有的消息都是在Handler所属的线程内处理的,所以虽然你用post(Runnable r),发给MessageQueue一个Runnable,但这并不会创建新的线程来执行,处理此消息时仅是调用r.run()。(想要另起线程执行,必须把Runnable放到一个Thread中)。
实例
这里用一个实例来展示主线程通过Handler与后台线程进行通信,并且主线程用Handler来实现循环时序。
播放一个视频,线程用于创建和初始化MediaPlayer,初始化好后会通过主线程的Handler告诉主线程,然后主线程可以播放视频,在播放过程中通过sendMessageDelayed()来实现播放进度的不断更新:
分享到:
相关推荐
Android源代码:HandlerDemo。。。。。。。。。。。。
import android.os.Handler; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { ...
Android中Handler的学习实例,在本示例中,在主线程外开启子线程(使用匿名内部类Runnable),使用Handler中的Message传递消息(高效),操作一个ProgressBar的进度。适合初学者学习和了解Handler以及ProgressBar的...
Android 开发技巧:音乐播放器的后台处理【Service、Handler、MediaPlayer】完整代码
嵌入式Android项目设计与开发 第七章 多线程 ——(3)UI线程冲突 多线程 即使Android可以使用线程, 但规定不能使用子线程修改主线程的内容。 多线程 可以考虑在子线程中使用runOnUiThread重新载入UI线程,并干预...
android demo,使用Handler的postDelay,Runnable run实现延时3秒的splash。
这是Pro Android学习系列中Android Service部分的例子源代码。相关学习笔记见:http://blog.csdn.net/flowingflying/article/details/6212512
异步请求分页示例:handler.ashx + $.ajax() + Json + 前端分页处理
HandlerThread handlerThread = new HandlerThread("handler_thread"); //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start()方法,否则获得的值为空值; handlerThread.start(); //创建...
简单实现更新UI的操作,仅供学习参考 这里用到handler类,runnable类,按钮的点击事件
Android Weak Handler Memory safer implementation of android.os.Handler Problem Original implementation of Handler always keeps hard reference to handler in queue of execution. Any object in Message or...
demo01: 通过handler.post()的方法可以更新ui demo02: 一秒钟切换一张图片 demo03: 霓虹灯动态效果的显示 demo04: 倒计时,停止倒计时 demo05: 通过handler.sendMessage和handleMessage发送处理消息 demo06: message...
NULL 博文链接:https://bijian1013.iteye.com/blog/2340632
当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理...
1.handler是什么? 2.handler怎么用? 3.为什么要用handler?
本篇文章是对在Android中Handler Runnable与Thread的区别进行了详细的分析介绍,需要的朋友参考下
【Android开发入门】Android线程之Handler
android:handler简单用法
compile ' com.github.xesam:AndroidTimer:v0.1 ' } 去做 添加股票行情顺序 使用 计数计时器 new CountTimer ( 100 ) { @Override public void onTick ( long millisFly ) { // millisFly is the Elapsed time ...
android 中Handler 的几种写法,很简单的demo,大神简单修改下,用的是Handler.Callback,的方法