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打交道,因 ...
随机推荐
- C#事务相关
之前在程序中用到事务时,都是在存储过程中创建事务来对数据进行控制,其实在C#中也有事务类. 1.DbTransaction类对数据库访问添加事务,它是对数据库事务操作的基类,继承此类的有: Sys ...
- thinkphp扩展 根据前端批量建立字段
/*批量添加字段辅助*/ function add_colum($tabel){ foreach ($_POST as $key=>$value){ $array[] = "add & ...
- thinkphp文章列表及删除文章
出师不利,数据一次删完了... 教程:http://www.thinkphp.cn/topic/9757.html 首先要构造mysql数据库 模板代码 </head> <body& ...
- Java 多线程Thread和Runnable
Thread: class MyThread extends Thread { private int ticketsCont=5; //一共有5张火车票 private String name; / ...
- Python模块 (psutil)
psutil psutil是Python中一个系统信息检索模块,可以获取(系统.CPU.内存.网络.磁盘)等信息,可以应用于系统的监控.健康状态检查,等同于shell中的ps.free.top.df功 ...
- .Net内存优化的几点经验
以前从来没有想过.Net开发居然存在内存无法释放的问题,总是认为GC给我处理好了一切.现在GIS二次开发结合三维球开发,没有想到存在如此严重的内存增长,很快内存就不够用了,导致系统各种不稳定.球体和三 ...
- TCP/IP之TCP的建立与终止
TCP协议简介 tcp/ip协议族中传输层最重要的两种协议是UDP和TCP协议,上一篇文章用很短的篇幅介绍完了UDP协议相关的内容,但相对于UDP而言的TCP协议,是种更复杂,应用更广的协议.在接下来 ...
- REST Security with JWT using Java and Spring Security
Security Security is the enemy of convenience, and vice versa. This statement is true for any system ...
- canvas 基础知识整理(一)
canvas这个 HTML 元素是为了客户端矢量图形而设计的.它自己没有行为,但却把一个绘图 API 展现给客户端 JavaScript 以使脚本能够把想绘制的东西都绘制到一块画布上. html的基本 ...
- SQL注入攻击之关键字检测
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来.我们都知道计算机技术发展日新月异,速度惊人的快,你我稍不留神,就会被慢慢淘汰!因此:每日不间断的学习是避免被 ...