Android正在使用Handler实现消息分发机制(零)
演讲前,AsyncTask文章。我们在最后谈到。AsyncTask它是利用Handler异步消息处理机制,操作结果。使用Message回到主线程,从而执行UI更新线程。
而在我们的日常开发工作,Handler一类是经常使用在我们中间,然后Handler的主要作用是什么?
Handler 的主要作用就是对消息(消息能够是我们想做的一些UI更新,也能够是其它的一些不可见的操作,如操作数据库等)的异步处理机制。而相信大家都了解异步的概念。
简单地说一下:
1)从程序的角度来看,就是当运行某行代码的时候,发送了一个异步请求(消息)。程序不须要在此行代码上继续等待下去。而是可以继续运行之后的代码。
2)从用户的角度来看,用户发送了一个消息。不须要什么事也不做,就在那傻等,而能够去做其它的事情。当相应的消息被处理完之后 ,就会通过回调机制处理相应的结果。
所以。Android中Handler的消息异步处理机制,可以给用户提供一个更加合理及友好的用户体验。
当然。Android是用Handler来实现。其它的平台环境。也有着自己的一套异步实现机制,原理一样,名称不同而已。
既然我们是做Android开发的。那么我们肯定就要好好地学习一下Handler的使用。探究一下隐藏在Handler之后的代码架构。
首先。我们还是从简单的样例来入门。学习一下,怎样使用Handler。
代码例如以下:
public class MainActivity extends ActionBarActivity {
private static final int MSG_ID_1 = 1;
private static final int MSG_ID_2 = 2;
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ID_1:
Log.v("Test", "Toast called from Handler.sendMessage()");
break;
case MSG_ID_2:
break;
}
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Message message = mHandler.obtainMessage();
message.what = MSG_ID_1;
mHandler.sendMessage(message);
}
}
当我们启动程序的时候。我们能够看到,在LogCat里面就会看到,已经打印出了例如以下的信息:
10-27 15:13:21.382: V/Test(9618): Toast called from Handler.sendMessage()
而这正是我们在handler的handleMessage中对msg.what = MSG_ID_1 的情况下进行处理的。
从这个简单的样例,我们能够归纳一下Handler的使用步骤,大概有下面几步:
1)创建一个Handler对象。而且实现其 handleMessage(Message msg) 方法,如代码中:
private Handler mHandler = new Handler() {
而实现handleMessage方法一步。我们能够看到,会获取一个Message对象。
Message对象封装了一些參数。经常使用的大概有下面几个:
a)what 參数:这是一个 int 值,常常是我们用来区分消息的一个ID,比方样例中,我们将MSG_ID_1在创建消息的时候赋值给msg.what。
b)obj 參数:这是一个Object对象。
通过obj參数,能够把不论什么对象赋给消息,然后在handleMessage中进行处理,而这也是Handler在异步处理中传递数据的方法。
c)arg1, arg2 等參数:上述a),b) 两个參数是我们最经常使用的Message的參数了,基本上也须要这两个參数就足够了,只是Message还是提供了其它的一些字段供我们使用。如argX等。也就是 arguments的缩写。arg1和arg2是Android提供的所谓low-cost的变量,只是一般也就是用来设置一些int值。
d)data參数,data參数是一个Bundle类型的对象,我们能够通过setData方法来设置bundle。就跟我们在Activity之间利用Intent传递数据一样来使用。
2)当创建好Handler对象之后,第二步就须要创建一个Message对象了。创建Message对象有两种方法:
2.1)直接创建新对象,代码例如以下:
Message msg = new Message()
2.2)利用Handler.obtainMessage()方法,也即上面代码中使用的方式。例如以下:
Message message = mHandler.obtainMessage();
普通情况下,我们建议使用另外一种方式。为什么呢?
由于在Message的内部中维护了一个类似消息池的对象,当我们使用Handler来对Message进行分发的时候,处理完之后,Message对象并不一定会被立即销毁。而是有可能放到一个消息池中。
当利用Handler的obtainMessage方法,Handler会去从消息池中获取一个已经存在的对象。并初始化好其信息。这样,我们就不须要再又一次去创建一个对象,浪费一些内存,在嵌入式应用,内存不是非常大的情况下,这是对性能的一种优化。
在创建Message的时候,我们就能够对msg.what进行赋值,目的就是为了Handler在handleMessage的时候,能够推断这个消息的用途或目的是什么。
当然,不同的需求,肯定有不同的处理。这就详细情况详细分析了。
3)当消息(Message)创建好了之后,我们就能够利用Handler的sendMessage来进行发送消息了,之后。这个消息就会被其handler所捕获,从而进行处理了。
接下来,我们就再扩充一下这个样例,代码例如以下:
public class MainActivity extends ActionBarActivity {
private static final int MSG_ID_1 = 1;
private static final int MSG_ID_2 = 2;
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ID_1:
Log.v("Test", "Toast called from Handler.sendMessage()");
break;
case MSG_ID_2:
String str = (String) msg.obj;
Log.v("Test", str);
break;
}
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Message message = mHandler.obtainMessage();
message.what = MSG_ID_1;
mHandler.sendMessage(message);
Message msg2 = mHandler.obtainMessage();
msg2.obj = "I'm String from Message 2";
msg2.what = MSG_ID_2;
mHandler.sendMessage(msg2);
}
}
而其相应的结果例如以下:
10-27 15:35:19.168: V/Test(12135): Toast called from Handler.sendMessage()
10-27 15:35:19.168: V/Test(12135): I'm String from Message 2
由此,我们能够看到。利用obj參数,我们将String对象给传到handleMessage中去了。
除了 sendMessage方法,发送消息时, Handler还可使用例如以下的方法:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
} public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
而事实上,不管是还是sendMessage还是使用post方法,事实上终于都是通过调用sendMessageAtTime方法,将相应的Message对象放入一个MessageQueue中的。
那么其为什么要放到MessageQueue?放到MessageQueue中有怎样跑回到Handler的handleMessage中的呢?
接下来的文章。我们再继续来学习。
这一篇我们就简单介绍了如何使用Handler,简单的示例。只是入门。
结束。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
Android正在使用Handler实现消息分发机制(零)的更多相关文章
- Android正在使用Handler实现消息分发机制(两)
在开始这篇文章之前,.首先,我们在总结前两篇文章Handler, Looper和MessageQueue像一些关键点: 0)在创建线程Handler之前,你必须调用Looper.prepare(), ...
- Android中利用Handler实现消息的分发机制(三)
在第二篇文章<Android中利用Handler实现消息的分发机制(一)>中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而假设在子线程中须要去 ...
- delphi VCL研究之消息分发机制-delphi高手突破读书笔记
1.VCL 概貌 先看一下VCL类图的主要分支,如图4.1所示.在图中可以看到,TObject是VCL的祖先类,这也是Object Pascal语言所规定的.但实际上,TObject以及TObject ...
- Cocos2d-x 3.0 屏幕触摸及消息分发机制
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- Android 消息分发机制
Android 中针对耗时的操作,放在主线程操作,轻者会造成 UI 卡顿,重则会直接无响应,造成 Force Close.同时在 Android 3.0 以后,禁止在主线程进行网络请求. 针对耗时或者 ...
- Android为TV端助力 事件分发机制
android事件分发机制,给控件设置ontouch监听事件,当ontouch返回true时,他就不会走onTouchEvent方法,要想走onTouchEvent方法只需要返回ontouch返回fa ...
- Android面试收集录6 事件分发机制
转自:秋招面试宝典. 一. 基础认知 1.1 事件分发的对象是谁? 答:事件 当用户触摸屏幕时(View或ViewGroup派生的控件),将产生点击事件(Touch事件). Touch事件相关细节(发 ...
- 轻松搞定RabbitMQ(二)——工作队列之消息分发机制
转自 http://blog.csdn.net/xiaoxian8023/article/details/48681987 上一篇博文中简单介绍了一下RabbitMQ的基础知识,并写了一个经典语言入门 ...
- Android正在使用Handler实现信息发布机制(一)
上一篇文章,我们谈到了电话Handler的sendMessage方法,最后,我们将进入一个电话 sendMessageAtTime方法,例如下列: public boolean sendMessage ...
随机推荐
- [Math Processing Error] 问题的解决(F5刷新页面与 Ctrl/Shift + F5 刷新页面的区别)
Why is [Math Processing Error] all over the place today? 当打开某页面出现 [Math Processing Error],一般表示 MathJ ...
- 贝叶斯统计(Bayesian statistics) vs 频率统计(Frequentist statistics):marginal likelihood(边缘似然)
1. Bayesian statistics 一组独立同分布的数据集 X=(x1,-,xn)(xi∼p(xi|θ)),参数 θ 同时也是被另外分布定义的随机变量 θ∼p(θ|α),此时: p(X|α) ...
- ios开发网络学八:NSURLSession相关代理方法
#import "ViewController.h" @interface ViewController ()<NSURLSessionDataDelegate> /* ...
- 菜单之二:使用xml文件定义菜单 分类: H1_ANDROID 2013-11-03 09:39 1038人阅读 评论(0) 收藏
参考<疯狂android讲义>2.10节 P174,参见归档project:XmlMenuDemo.zip 一般推荐使用XML文件定义菜单. 基本步骤如下: 1.定义布局文件 为简单显示原 ...
- linux 系统升级中的一些配置
1. 关闭IPV6 vi /etc/sysconfig/network NETWORKING_IPV6=no #掉 source /etc/sysconfig/network vi /etc/m ...
- .NET Framework基础知识(二)(转载)
1.课外:为什么object数组可以赋值给object类型,int数组却不能赋值给int类型? 答:因为不管是什么什么数组都继承自Array,而Array又继承自object. 2.线程:是操作系统分 ...
- nas docker xunlei
http://bbs.xunlei.com/thread-389018-1-1.html 首先,启动远程服务,找到你的设备IP,在浏览器里输入以下地址,host换成你设备的IP http://host ...
- 浅谈python字符串存储形式
http://blog.csdn.net/zhonghuan1992 钟桓 2014年8月31日 浅谈python字符串存储形式 记录一下自己今的天发现疑问而且给出自己现有知识有的回答. 长话短说,用 ...
- 常用binlog日志操作命令
1.查看所有binlog日志列表 mysql> show master logs; 2.查看master状态,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Po ...
- duplicate symbols for architecture
duplicate symbols for architecture XCODE编译的时候报错:duplicate symbols for architecture armv7 1.首先排查是 ...