handle作用:是满足线程与线程之间通信的
线程一旦被创建就会生成一个Looper对象,有且仅有一个
每个应用在运行的时候都会创建一个主线程(mainThread)。
主线程不能做耗时操作,子线程不能更新UI
Looper:一个线程可以产生一个Loop对象,由它来循环MessageQueue(消息队列)
handler:通过Handler对象和Looper进行沟通,以便发送消息到MessageQueue或者接收Looper从MessageQueue中读取的消息
MessageQueue:用来存放线程放入的消息
线程:UIThread通常就是mian thread,而Android启动程序的时候就会替它建立一个MessageQueue。
private Handler handler = new Handler() { //接收子线程中发送过来的消息 @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: //通过obj的方式来获取方法 text_tv.setText((String) msg.obj); break; case 2: //通过bundle的方法来获取数据 text_tv.setText((String) msg.getData().getString("message")); break; case 3: //通过bundle的方法来获取数据 text_tv.setText((String) msg.getData().getString("data")); break; } } };
第一种是通过new Message()的方法来新建消息(
属于最原始的写法,但是其弊端是没有回收利用机制,如果一个APP中新建了很多消息而没有回收,那么会带来系统可卡顿,不利于系统的优化),通过what添加标识,通过obj添加内容存放数据(
当然我们也可以通过bundle来存放数据,都是可以的)。
new Thread() { @Override public void run() { //使用handler进行献策之间的消息通信 Message message = new Message(); //给message添加标识 message.what = 1; //给message添加内容 message.obj = "今天天气不错"; //向消息队列中发送消息 handler.sendMessage(message); } }.start();
第二种是通过Message.obtain的方法(
这种方式是最常用的,因为此方式创建的消息可以被回收利用,而且也很方便),也是通过what来添加标识,通过bundle来存放数据(
也是可以用obj来存放,都一样)。
new Thread() { @Override public void run() { //通过Message的obtain来创建消息,那么此消息可以被回收利用 Message obtain = Message.obtain(); obtain.what = 3; bundle.putString("data", "下雪了今天。"); obtain.setData(bundle); handler.sendMessage(obtain); } }.start();
用bundle存放数据和用obj存放数据的利弊:
bundle是一个键值对,可以定义成一个全局变量,进而多次使用,每次传不同的键名即可。而且bundle所传的的数据类型明确指明的有很多,传不同类型时很方便,和intent有点类似。
obj是一个万能的类型,可以传任何类型,但是拿的时候要强转,并且对于一些特殊类型不如bundle使用方便。当然,对于基本数据类型,还是obj来的方便一点。
new Thread(){ @Override public void run() { Message msg = new Message(); //使用bundle来存放数据,可以放集合 bundle.putString("message", "太阳出来了"); msg.setData(bundle); msg.what = 2; handler.sendMessage(msg); } }.start();
注:消息时不能抽成全局变量来使用,无论是使用new Message的方法还是通过Message.obtain的方法,都是只能此时创建此时用。