Bundle
1.新建一个Bundle类
Bundle bundle=new Bundle();
2.Bundle类中放入数据(key-value的形式,另一个Activity里面取数据的时候,通过key值找出对应的value值)
bundle.putString("key" ," value");
3.新建一个intent对象,并将该bundle加入到这个intent对象
Intent intent=new Intent( );
intent.putExtras(bundle);
4.获取key所对应的value
Bundle bundle=getIntent().getExtras();
String data=bundle.getString("key");
Bundle是一个简单的数据携带包,该对象也包含了多个方法来存入数据:
putXxx(String key, Xxx data):向Bundle中放入Int、Long等各种类型的数据
putSerializable(String key, Serializable data):向Bundle中放入一个可序列化的对象
取出Bundle数据携带包里的数据的方法:
getXxx(String key):从Bundle取出Int、Long等各种类型的数据
getSerializable(String key,Serializable data):从Bundle取出一个可序列化的对象
项目中使用:Bundle
1.消费完以后把信息存到bundle中,发送到handler中
Bundle bundle =new Bundle();
bundle.putBoolean("Recharge", Consume.HashRecharge);
bundle.putString("card_id",String.format("%0"+10+"d", Long.valueOf(Consume.CardId , 16)));
bundle.putString("studentname", Consume.studentname);
bundle.putString("balance", String.valueOf(Consume.balance));//balance是余额
bundle.putString("notification","2+ 扣费成功");
bundle.putString("url", ActivityContents.QR_forPay+"/card_num/"+Consume.CardId);
//ActivityContents.ConsumeResultNoOverTime = 26 是handler功能
Message.obtain(handler,ActivityContents.ConsumeResultNoOverTime,bundle).sendToTarget();
2.在handler中处理消息
private void InitHandler(){
mHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what){
case ActivityContents.CostShowNoOverTime:
Bundle bun=(Bundle)msg.obj;
notification_text.setText(bun.getString("notification"));
balance_text.setText(bun.getString("balance"));
student_name.setText(bun.getString("studentname"));
student_cardId.setText(bun.getString("card_id"));
textcost.setText(bun.getDouble("sum")+"元");
if(!bun.getString("notification").equals("请于感应区刷卡")){
mSerialdriver.McuShow(mSerialdriver.Action_StudentMessage, bun.getString("balance","0")+"+"+
bun.getString("studentname"," "));
mSerialdriver.McuShow(mSerialdriver.Action_MessageFailShow, bun.getString("notification"));
}
break;
}
};
}
Handler
Handler既是发送者也是接收处理者,一个消息发送出来,交由哪个Handler去处理,这个完全取决于这个消息的发送者是哪个Handler。即一个Handler发送的消息,只能交由自己去处理。要做到异步线程进行通信,关键在于在A线程中拿到B线程的Handler,拿到之后就可以使用B线程的Handler去发送消息,交由B线程去处理消息了。线程与Handler之间是多对一的关系,一个线程可以有多个Handler,一个Handler只能且必须绑定一个线程。一个线程有多个Handler(使用场景会在后面介绍),用于处理不用类型的消息。
使用Handler的表现形式有两种:
- (1)通过发送消息(sendMessage方法)接收消息(接收消息即回调该Handler的handleMessage方法)并处理的形式;
- (2)通过发送Runnable对象的形式,直接让该Handler所在线程执行其run方法。即调用post(Runnabler)方法。
需要注意的是:(1)该Runnable也会被包装成一个消息的形式进行传递。(2)整个过程并没有另外新建线程,该Runnable在Handler所在线程执行
如何使用 :
1.创建 Handler
private Handler handler = new Handler() {
// 重写 handleMessage 来根据不同 what 来处理 Message
// 这个方法在 Handler 创建的线程执行
@Override public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
MLog.i(msg.obj);
break;
case 1:
break;
default:
}
}
};
2.创建并发送 Message
// 获取一个 Message
Message message = Message.obtain();
message.what = 0;
message.obj = new Object();
// 使用 Handler 发送 Message
// 消息发送完成后 Handler 的 handleMessage(Message msg) 会处理消息
handler.sendMessage(message);
// 延迟 1s 发送 Message
handler.sendMessageDelayed(message, 1000);
// 发送一个空的 Message
handler.sendEmptyMessage(msg.what);
// 延迟发送一个空的 Message
handler.sendEmptyMessageDelayed(0, 1000);
// 还可以这样
// 创建 Message 并绑定 Handler
Message message = handler.obtainMessage();
message.what = 0;
message.obj = new Object();
// 发送 Message
message.sendToTarget();
3.使用 Handler 子线程请求数据,主线程刷新 UI
// 1. 在主线程创建 Handler(略)
// 2. 子线程请求数据,主线程刷新 UI
new Thread(new Runnable() {
@Override public void run() {
// 获取网络数据
final List<Object> datas = getNetData();
// 方法一:将数据作为 Message 的 obj 发送出去,在 handleMessage 中刷新 UI
Message msg = Message.obtain();
msg.what = 1;
msg.obj = data;
handler.sendMessage(msg);
// 方法二:直接在 post 中刷新 UI
handler.post(new Runnable() {
@Override public void run() {
// 使用 datas 刷新 UI
// 这个方法也会在 Handler 创建的线程执行
}
});
}
}).start();
项目中使用
1.在MainActivity中
public static Handler mHandler;
public PictureThread mPictureThread;//上传图片推送线程
private SerialPortDriver mSerialdriver;//串口通信线程
onCreate()
startThreads();
InitHandler();
//1.创建 Handler
private void InitHandler(){
mHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what){
case ActivityContents.MobileNetwork:
break;
case ActivityContents.NetworkOFF:
break;
case ActivityContents.ConsumeResult:
//那边发来的消费结果这里处理:
break;
}
}
};
}
//开启线程
private void startThreads(){
mPictureThread = new PictureThread(mContext); //上传图片推送接口
new Thread(mPictureThread).start();
mSerialdriver = new SerialPortDriver(context); //串口通信线程
new Thread(mSerialdriver).start();
}
2.在SerialPortDriver中,这是处理单片机传进来的类。这个类 通过实现Runnable接口创建线程
知识点
通过实现Runnable接口创建线程
(1).定义一个类实现Runnable接口,重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).创建Runnable接口实现类的对象。
(3).创建一个Thread类的对象,需要封装前面Runnable接口实现类的对象。(接口可以实现多继承)
(4).调用Thread对象的start()方法,启动线程
public class SerialPortDriver implements Runnable,Global{
private Handler handler;
private Message msg=null;
private Bundle bundle=null;
public SerialPortDriver(Context context) {
this.handler=MainActivity.getHandler();
Message.obtain(handler,RecordShow,2).sendToTarget();
mReadThread = new ReadThread();
mReadThread.start();
}
@Override
public void run() {
addFirstAnsTask(new picTask(AnswerBuffer));
}
private class ReadThread extends Thread{
@Override
public void run() {
super.run();
Message.obtain(handler,ActivityContents.ConsumeResult,bundle).sendToTarget();
//handler在这里发送消息,此handler是: this.handler=MainActivity.getHandler();
}
}
extends Thread 与 implements Runnable 的区别
(1).首先定义一个类去继承Thread父类,重写父类中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).直接创建一个ThreadDemo2类的对象,也可以利用多态性,变量声明为父类的类型。
(3).调用start方法,线程t启动,隐含的调用run()方法。
两种方式的比较
首先分析两种方式的输出结果,同样是创建了两个线程,为什么结果不一样呢?
使用实现Runnable接口方式创建线程可以共享同一个目标对象(TreadDemo1 tt=new TreadDemo1();),实现了多个相同线程处理同一份资源。
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法
3.使用 Handler 子线程请求数据,主线程刷新 UI
//开启线程
private void startThreads(){
mPictureThread = new PictureThread(mContext); //上传图片推送接口
new Thread(mPictureThread).start();
mSerialdriver = new SerialPortDriver(context); //串口通信线程
new Thread(mSerialdriver).start();
}
sendToTarget与sendMessage的区别
1、 message 从handler 类获取,从而可以直接向该handler 对象发送消息。target就是创建message的handler
Message msg = handler.obtainMessage();
msg.sendToTarget();
2、new出来的message或者通过Message.obtain的方式创建的message,可直接调用 handler 的发送消息方法来发送消息。
Message msg=new Message();
//Message msg= Message.obtain();
handler.sendMessage(msg);
示例:
/*1、message由handler创建,可直接向handler发送消息。msg.sendToTarget()*/
Message msg = handler.obtainMessage();
msg.arg1 = i;
msg.sendToTarget();
/*2、message通过new的方式创建,可用handler.sendMessage(msg)来发送消息*/
Message msg=new Message();
msg.arg1=i;
handler.sendMessage(msg);
//直接调用 handler 的发送消息方法发送消息。
/* 3、message通过Message.obtain的方式创建,可用sendMessage(msg)来发送消息 */
Message msg= Message.obtain();
msg.arg1=i;
handler.sendMessage(msg);