Android消息处理机制(Handler 与Message)---01
一、handler的使用场景为么会有handler?(部分内容图片摘自http://www.runoob.com/w3cnote/android-tutorial-handler-message.html)
二、handler的消息处理机制
在Android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知。
- UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue;
- Handler:作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
- Message:Handler接收与处理的消息对象
- MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
- Looper:每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!
通俗一点讲:当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送信息;而我们发送的信息会先到主线程的MessageQueue进行等待,由Looper按先入先出顺序取出,再根据message对象的what属性分发给对应的Handler进行处理!
三、Handler的相关方法
在使用android的消息的处理机制的时候:一般是有两种手段,
1、该message自己绑定到目标handler后,自行进入messageQueue,等待handler接受处理。Message方法:public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) ,通过该方法可以获得一个消息:Message message = Message.obtain(handler, 33, 2, 3, "hello");
发送消息的方式,有一点将自己绑定好了被发射的感觉,message.sendToTarget(); ---被动(意会)
2、handler主动设置要发送的消息的各个属性值:arg1,arg2,obj,what。方法:public final Message obtainMessage(int what, int arg1, int arg2, Object obj) 通过该方法也可以获得一个消息:比如Message message = handler.obtainMessage(3, 1, 2, "java");
然后将设置好的消息,由handler发送出去:handler.sendMessage(message);----主动(自己意会的)。下面十几个常用方法:
- void handleMessage(Message msg):处理消息的方法,使用handleMessage去处理消息,里面的参数Message msg既是在messageQueue里面取出的消息message~
- sendEmptyMessage(int what):发送空消息
- sendEmptyMessageDelayed(int what,long delayMillis):指定延时多少毫秒后发送空信息
- sendMessage(Message msg):立即发送信息
- sendMessageDelayed(Message msg):指定延时多少毫秒后发送信息
- final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息 如果是参数为(int what,Object object):除了判断what属性,还需要判断Object属性是否为指定对象的消息
//========================
//废话不多说直接上demo:由上图中的图2可以看出消息的处理是在一条全新的线程中进行的,因此关键的是要新建一个thread,在它的run方法中执行消息的发送,
// 首先是被动方式:
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.View;
import android.widget.Button; /**
* 此处重点熟悉message的属性~,将message绑定到目标handler,然后直接使用message的方法将消息发送~,被动发送。
* @author
*
*/ // 在安卓开发中是绝对不能使用UI主线程去访问网络 的,一定是要开一条新的线程去访问然后把结果返回
public class MainActivity extends Activity {
private Button button; // handler对象,用来接收消息~
private Handler handler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) { //这个是发送过来的消息
// 处理从子线程发送过来的消息
int arg1 = msg.arg1; //获取消息携带的属性值
int arg2 = msg.arg2;
int what = msg.what;
Object result = msg.obj;
System.out.println("-arg1--->>" + arg1);
System.out.println("-arg2--->>" + arg2);
System.out.println("-what--->>" + what);
System.out.println("-result--->>" + result);
Bundle bundle = msg.getData(); // 用来获取消息里面的bundle数据
System.out.println("-getData--->>"
+ bundle.getStringArray("strs").length);
};
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button1); button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
// 启动一个子线程
new Thread(new MyThread()).start(); //一定要在这里面启动!
}
});
} public class MyThread implements Runnable {
@Override
public void run() { //run方法里面写要发送的消息对象,并对消息携带的信息进行定义!!
// TODO Auto-generated method stub // 第一种方式:获取消息
// Message message = Message.obtain();
// message.what = 1;
// message.arg1 = 2;
// message.arg2 = 3;
// message.obj = "jack";
// handler.sendMessage(message); // 第二种方式
// Message message = Message.obtain(handler);
// message.what = 1;
// message.arg1 = 2;
// message.arg2 = 3;
// message.obj = "jack";
// //handler.sendMessage(message);
// //此时在构造方法里面已经将message的target绑定了handler不需要再次发送了。
// message.sendToTarget(); // 第三种方式,和上面是没有区别的。。
// Message message = Message.obtain(handler, 33);
// message.arg1 = 2;
// message.arg2 = 3;
// message.obj = "jack";
// message.sendToTarget(); // 第4种方式这几种方式都是大同小异,只不过是内部封装了而已,使用的时候根据实际需要就可以了。
Message message = Message.obtain(handler, 33, 2, 3, "hello");
Bundle data = new Bundle(); //message也可以携带复杂一点的数据比如:bundle对象。
data.putStringArray("strs", new String[] { "c", "c++", "java" });
message.setData(data);
message.sendToTarget(); // 不可忘!
}
}
}
// ================================布局文件就不给出了,就是一个按钮然后为该按钮绑定了事件。
// =============================handler的主动发送消息
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; /**
* 此处主要是使用handler的主动抓取、发送message功能!在messaQequue里面
*
* @author *
*/
public class MainActivity extends Activity implements OnClickListener {
private Button button, button2; // Handler可以接受发送消息,从消息队列中提取消息用于更新UI,这里都没有对UI进行操作,主要是介绍如何定义自己的message如何发送这个message,最后将会给一个demo
private Handler handler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) { System.out.println("-arg1--->" + msg.arg1);
System.out.println("-arg2--->" + msg.arg2);
System.out.println("-what--->" + msg.what);
System.out.println("-obj--->" + msg.obj);
};
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2); button.setOnClickListener(this);
button2.setOnClickListener(this);
} @Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button1:
new Thread(new Runnable() { //使用匿名内部类的方式,这个无难点吧。。。
@Override
public void run() {
// TODO Auto-generated method stub
// handler发送消息的第一种方式
// handler.sendEmptyMessage(3); // handler发送消息的第二种方式,第二个参数是指定在指定的时间上发送消息,这个是确定的某个时间!
// 可以通过获取当前的系统时间后SystemClock.uptimeMillis()再加上某个时间,如果给出的时间小于当前时间则立即发送,亲测
//而且感觉这个功能很bug的,在特定的时间,需要我们人为的去计算:SystemClock.uptimeMillis()+myTime(这个是你想在多少毫秒后启动的毫秒值)
// handler.sendEmptyMessageAtTime(3, X+3000);
// handler发送消息的第三种方式,这个效果是在3000毫秒后延迟。
60 // handler.sendEmptyMessageDelayed(3, 3000); // handler发送消息的第四种方式
// Message message = Message.obtain(); //这个是使用message被动得到
// Message message = handler.obtainMessage(); //
// handler的主动获取消息,在源码方面一样!无区别。
// message.arg1 = 1;
// message.arg2 = 2;
// message.obj = "java";
// message.what = 4;
// 使用handler发送消息的第五种方式,原理都是一样的~
//我最习惯还是message自己搞自己的事情别去干发送的活,message需要携带的属性由他自己搞,剩下的发送接收处理的体力劳动由handler搞。
Message message = handler.obtainMessage(3, 1, 2, "java");
72 handler.sendMessage(message);
}
}).start(); //记得启动
break;
case R.id.button2:
// 第二个按钮使用post方式发送消息,该方法需要一个runnable的实例,使用匿名内部类的方式实现。
// 直接使用一个匿名内部类Runnable来执行1.获取消息对象;2.发送消息对象。换汤不换药,通过看源码也可以知道背后的实现都是一个道理。
handler.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Message message = handler.obtainMessage(23, 21, 22, "postMessage");
handler.sendMessage(message);
}
});
break;
}
} }
//-----------------------------------具体应用handler来更新UI
//========================================
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.BitmapFactory;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView; public class MainActivity extends Activity {
private Button button;
private ImageView imageView;
private String image_path = "http://www.deskcar.com/desktop/fengjing/200895150214/21.jpg";
private final int IS_FINSIH = 1;
private ProgressDialog dialog = null; // 标准的写法
private Handler handler = new Handler() {
// 使用handleMessage去处理消息!!,里面的参数Message msg既是发送过来的参数~
@Override
public void handleMessage(android.os.Message msg) {
//
// 在此接受发送过来的消息<---msg
byte[] data = (byte[]) msg.obj; //转型
// 将接受过来的数据赋值给imageview
imageView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0,
data.length));
// 标记~数据发送已经结束了?,此处有由代码的逻辑顺序来决定的,
if (msg.what == IS_FINSIH) {
dialog.dismiss();
}
};
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView1);
dialog = new ProgressDialog(this);
dialog.setTitle("提示");
dialog.setMessage("正在下载,请稍等...");
dialog.setCancelable(false); button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
// 开启线程
new Thread(new MyThread()).start();
dialog.show(); // 显示对话框他会直接先显示出来这个是位于主线程里面的。与thread互不影响。 }
});
} // 避免在UI主线程里面更新数据
public class MyThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
// 使用http完成网络下载的操作
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(image_path);
HttpResponse httpResponse = null;
//下面是我在http的使用过程中总结的一些心得,对于http没有经验,有错请指出。。。
/*
* 这种方式获取响应内容的实体~entity中的流对象!不建议使用了。比较麻烦, InputStream inputStream
* =null; inputStream = httpResponse.getEntity().getContent();
* 然后将该inputStream写入到ByteArrayOutputStream,然后该内存缓冲流可以转为字节数组byte[]=
* outputStream.toByteArray();
*/
// 使用http新的就是通过httpclient执行要执行的get/或者post方法然后获取服务端响应过来的实体对象entity;
// 然后从该entity中获取需要的数据比如inputstream/文件的长度等。。。一般我们的最终目的都是获取一个字节数组!byte[]只有二进制的数据才是数据的终极形态!
// 在使用的时候为了方便操作有一个工具类可以帮助我们简单的获取二进制数组
try {
httpResponse = httpClient.execute(httpGet);// client执行请求~典型的面对对象:客户端对象取执行请求的方法,获得返回的内容对象。通过工具来解析内容
// 判断连接是否正常
if (httpResponse.getStatusLine().getStatusCode() == 200) { HttpEntity entity = httpResponse.getEntity(); //获取响应头的实体内容
// 使用EntityUtils
byte[] data = EntityUtils.toByteArray(entity);
// 到了这里就是需要把我们的数据发送给UI主线程,二进制数组是最好的发送对象!!!
// Message message = new Message() 该方法是创建而不是在的当前的线程池取出。
Message message = Message.obtain();
message.obj = data;
message.what = IS_FINSIH; // 结束标志位
handler.sendMessage(message); // 将数据发送过去~
} } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
---------------如有侵犯,请告知。
Android消息处理机制(Handler 与Message)---01的更多相关文章
- (转)Android消息处理机制(Handler、Looper、MessageQueue与Message)
转自 http://www.cnblogs.com/angeldevil/p/3340644.html Android消息处理机制(Handler.Looper.MessageQueue与Messag ...
- Android消息处理机制(Handler、Looper、MessageQueue与Message)
Android是消息驱动的,实现消息驱动有几个要素: 消息的表示:Message 消息队列:MessageQueue 消息循环,用于循环取出消息进行处理:Looper 消息处理,消息循环从消息队列中取 ...
- 【Android 开发】: Android 消息处理机制之一: Handler 与 Message
最近几讲内容,我们学习了Android中关于多线程的一些知识,上一讲我们讲解了异步任务 AsyncTask 的操作,Android中还提供了其他的线程操作,如Handler Message Messa ...
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
解析Android消息处理机制 ——Handler/Thread/Looper & MessageQueue Keywords: Android Message HandlerThread L ...
- 7.1 基础知识Android消息处理机制
1. Android消息处理机制: Handler, MessageQueue, Looper, Thread 线程概念 : 一个应用程序运行时它的主体被称为进程, 一个进程内部可以有多个线程, 线程 ...
- Android架构分析之Android消息处理机制(二)
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的样例,本文我们 ...
- Android架构分析之Android消息处理机制(一)
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在这个系列文章中我们将来分析Android消息处理机制. 本文介绍了一个使用Han ...
- Android消息处理机制
Android消息处理机制 Android应用程序消息处理机制(深入到native,实际由管道实现-pipe&epoll)
- Android -- 消息处理机制源码分析(Looper,Handler,Message)
android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因 ...
随机推荐
- Power-BI 报表常用功能自适应设置
Power-BI 报表可以跨平台浏览,并自适应多种屏幕大小.在Power-BI 的开发界面下,就有多个属性用于设定在不同屏幕报表的展现方式,以达到更优的用户体验. 1.PC布局:设定报表在PC机上的布 ...
- EF Code First教程-02.1 Fluent API约定配置
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...
- underscore源码解析
(function() { // 创建一个全局对象, 在浏览器中表示为window对象, 在Node.js中表示global对象 var root = this; // 保存"_" ...
- 使用HttpClient抓取网站首页
HttpClient是Apache开发的第三方Java库,可以用来进行网络爬虫的开发,相关API的可以在http://hc.apache.org/httpcomponents-client-ga/ht ...
- Oracle忽略hint的几种情形
1.hint有语法错误.拼写错误 2.hint无效.比如索引不存在.非等值查询使用hash hint等 3.多个hint之间自相矛盾 4.hint受到了查询转换的影响 5.hint受到了数据库保留字的 ...
- css 去除标签默认样式
p,ul,ol,li,dl,dt,dd { list-style-type: none; margin: 0; padding: 0;}
- Linux内核源码分析方法
一.内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径.我们都 ...
- Beyond Compare
Beyond Compare是一个比较文件和文件夹的工具. 它可以帮助你找到并协调源代码.文件夹.图像和数据间的差异,即使包括zip文档中或者FTP站点上的文件. 另外它还可以同步化文件夹并验证不 ...
- Leetcode: Remove Elements
Given an array and a value, remove all instances of that value in place and return the new length. T ...
- 王家林 大数据Spark超经典视频链接全集[转]
压缩过的大数据Spark蘑菇云行动前置课程视频百度云分享链接 链接:http://pan.baidu.com/s/1cFqjQu SCALA专辑 Scala深入浅出经典视频 链接:http://pan ...