浅谈Handler
一、前言
年即将过完了,眼看有到上班时间了,今年打算换个新工作,所以要准备一下面试,今天简单看了一下handler,已被面试可能会问,再次也在博客上进行一下简单的记录,言归正传,浅谈Handler........,本博客只做知识简单梳理,大神勿看。
Handler:作用,在android中,android为我们提供了handler机制,帮我们完成,接受子线程传来的数据,更新UI线程得作用,大大方便了我们的使用。并且在activity生命周期中,各个回调方法的调用中,也是用到了Handler机制,来调用各个回调方法。
ps:作为知识回顾总结:
创建线程的方式:
一是,继承线程类Thread,并重写Run()
public class GetThread1 extends Thread{
@Override
public void run() {
super.run();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
二是,实现接口Runable
public class GetThread2 implements Runnable{
@Override
public void run() {
}
}
三是,直接new Thread()
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mytext.setText("ffff");
}
}).start();
二 、正文Handler基本使用
Handler可以在子线程中,分发Message对象和Runable对象到主线程中,每个Handler实例,都会绑定到创建它的线程中(一般位于主线程)。
它的两个作用:(1)、 安排消息或Runnable 在某个主线程中某个地方执行,
(2)、安排一个动作在不同的线程中执行
1、创建Handler对象方式:
(1)、直接new Handler()
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
viewPager.setCurrentItem(currentItem);// 切换当前显示的图片
};
};
(2)、继承Handler对象
private Handler getapphandler = new getAppHandler();
class getAppHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
//queryAppInfo();
break;
case 2:
getCompareAppInfos(isUserBigDate);
break;
default:
break;
}
}
}
2、Handler中分发消息的方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post类方法允许你排列一个Runnable对象到主线程队列中,
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post类方法允许你排列一个Runnable对象到主线程队列中,
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
发送Message:
Message msg;
发送一:
msg = Message.obtain(getapphandler,2);///获取message对象
msg.sendToTarget(); ///发送message
----------------------------------------------------------------------
Message msg = handler.obtainMessage();///通过Handler获取message对象
msg.what = xxx;
msg.arg1 = xxx;
msg.arg2 = xxx;
msg.obj = xxx;
msg.sendToTarget(); 发送
发送二:
Message msg = new Message()///自己new message
msg.what = xxx;
msg.arg1 = xxx;
msg.arg2 = xxx;
handler.sendMessage(msg);发送
性能异同比较:
建议以后创建Message对象时,使用Message msg = handler.obtainMessage();的形式创
建Message,不要自己New Message。因为此法创建,Message创建第一次时,是new的,第二三次再次使用时,
这里我们的Message 已经不是 自己创建的了,而是从MessagePool 拿的,省去了创建对象申请内存的开销。。。。。
然而发送message,使用obtainMessage 或者是 sendMessage 效率影响并不大.
Message msg;
发送一:
msg = Message.obtain(getapphandler,2);///获取message对象
msg.sendToTarget(); ///发送message
----------------------------------------------------------------------
Message msg = handler.obtainMessage();///通过Handler获取message对象
msg.what = xxx;
msg.arg1 = xxx;
msg.arg2 = xxx;
msg.obj = xxx;
msg.sendToTarget(); 发送
发送二:
Message msg = new Message()///自己new message
msg.what = xxx;
msg.arg1 = xxx;
msg.arg2 = xxx;
handler.sendMessage(msg);发送
性能异同比较:
建议以后创建Message对象时,使用Message msg = handler.obtainMessage();的形式创
建Message,不要自己New Message。因为此法创建,Message创建第一次时,是new的,第二三次再次使用时,
这里我们的Message 已经不是 自己创建的了,而是从MessagePool 拿的,省去了创建对象申请内存的开销。。。。。
然而发送message,使用obtainMessage 或者是 sendMessage 效率影响并不大.
实例代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mytext=(TextView) findViewById(R.id.mytext);
btn_post=(Button) findViewById(R.id.btn_post);
btn_post.setOnClickListener(new MyOnclickListen());
btn_stop=(Button) findViewById(R.id.btn_stop);
btn_stop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//将线程对象从队列中移除
mhandler.removeCallbacks(mRunable);
}
});
/**
* 创建子线程,在java中有两种方法实现线程体:
* 一是,继承线程类Thread
* 二是,实现接口Runable
*/
GetThread1 getThread1=new GetThread1();
getThread1.start();
/**
* 三是
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mytext.setText("ffff");
}
}).start();
*/
}
public class GetThread1 extends Thread{
@Override
public void run() {
super.run();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* 发送Message的方式:
* 获取Message方式:
* 第一种写法是message 从handler 类获取,从而可以直接向该handler 对象发送消息,
* Handler中obtainMessage与new Message的区别:
obtainmessage()是从消息池中拿来一个msg 不需要另开辟空间new
new需要重新申请,效率低,obtianmessage可以循环利用;
*
* 第二种写法是直接调用 handler 的发送消息方法发送消息。
*/
//第一种:obtainMessage
Message firstMessage=fristHandler.obtainMessage();
firstMessage.obj="test1 ";
firstMessage.sendToTarget();
//第二种:sendMessage
/*Message msg=new Message();
msg.obj="test";
Bundle b = new Bundle();// 存放数据
b.putString("color", "我的");
msg.setData(b);
fristHandler.sendMessage(msg);*/
}
}
发送三:使用post(Runnable)
/**
* 调用Handler的post()方法,将要执行的线程对象放到队列当中
*
* 这是android提供的一种机制,handler对象将通过post方法,
* 将里面的Runnable对象放到UI执行队列中,
* UI消费这个队列,调用Runnable的run方法。
*
* 虽然执行了new Runnable()这里并不生成新的线程。
* 因为Handler是绑定到UI主线程,Handler和UI主线程是同一个线程,
* HAndler的作用,主要是在其他后台线程中,通过handler这个媒介,
* 向UI主线程发送Runable对象。
*
*/
secondHandler.post(mRunable);
实例代码
private Runnable mRunable=new Runnable() {
@Override
public void run() {
//为了方便 查看,我们用Log打印出来
Log.e(TAG, Thread.currentThread().getName() + " " +count);
count++;
setTitle("" +count);
btn_post.setText(""+count);
//每2秒执行一次
mhandler.postDelayed(mRunable, 2000);
}
};
public class MyOnclickListen implements OnClickListener{
@Override
public void onClick(View arg0) {
/**
* 调用Handler的post()方法,将要执行的线程对象放到队列当中
*
* 这是android提供的一种机制,handler对象将通过post方法,
* 将里面的Runnable对象放到UI执行队列中,
* UI消费这个队列,调用Runnable的run方法。
*
* 虽然执行了new Runnable()这里并不生成新的线程。
* 因为Handler是绑定到UI主线程,Handler和UI主线程是同一个线程,
* HAndler的作用,主要是在其他后台线程中,通过handler这个媒介,
* 向UI主线程发送Runable对象。
*
*/
mhandler.post(mRunable);
}
}
post参考:
eg:http://byandby.iteye.com/blog/832467
三、Hander机制简介
1、Handler机制简述:
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;
或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;
或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue
2、handler的原理:
handler封装了消息的发送,主要包括消息发送给谁。
1)、Looper:
activityThread创建Ui线程时,通过ThreadLocal.set(new Lopper),set了Looper对象,
a、内部包含了一个消息队列也就是messageQueue,所有handler发送的消息都走向了消息队列。
b、通过looper.looper方法,就是一个死循环,不断从messageQueue去消息,如果有消息就处理,没消息就阻塞。
2)、MessageQueue:
就是一个消息队列,可以添加消息,并处理消息。
3)、Handler:
handler构造函数内部会跟Looper进行关联,即通过上面的ThreadLocal.get()得到Looper对象,也就是说在handler的内部可以找到Looper,找到Looper也就找到MessageQueue,在handler中发送消息,其实就是向 handler负责发送消息,looper负责接收handler发送的消息,并直接把消息回传给hanndler自己。
4)、messageQueue就是一个存储消息的容器。
1)、Looper:
activityThread创建Ui线程时,通过ThreadLocal.set(new Lopper),set了Looper对象,
a、内部包含了一个消息队列也就是messageQueue,所有handler发送的消息都走向了消息队列。
b、通过looper.looper方法,就是一个死循环,不断从messageQueue去消息,如果有消息就处理,没消息就阻塞。
2)、MessageQueue:
就是一个消息队列,可以添加消息,并处理消息。
3)、Handler:
handler构造函数内部会跟Looper进行关联,即通过上面的ThreadLocal.get()得到Looper对象,也就是说在handler的内部可以找到Looper,找到Looper也就找到MessageQueue,在handler中发送消息,其实就是向 handler负责发送消息,looper负责接收handler发送的消息,并直接把消息回传给hanndler自己。
4)、messageQueue就是一个存储消息的容器。
当你创建一个进程的时候,就回创建一个main线程,也就是activityThread线程,activityThread线程会在系统之中,
为我们创建默认去创建一个looper,Looper就回和MessageQuenen和UI线程,有联系。主线程运行MessageQuenene.
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,
该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。
之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化
的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Handler、Looper、MessageQueue的初始化流程如图所示:
Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,
子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。
UI主线程通过Looper循环查询消息队列UI_MQ,
当发现有消息存在时会将消息从消息队列中取出。
首先分析消息,通过消息的参数判断该消息对应的Handler,
然后将消息分发到指定的Handler进行处理。
为我们创建默认去创建一个looper,Looper就回和MessageQuenen和UI线程,有联系。主线程运行MessageQuenene.
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,
该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。
之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化
的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Handler、Looper、MessageQueue的初始化流程如图所示:
Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,
子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。
UI主线程通过Looper循环查询消息队列UI_MQ,
当发现有消息存在时会将消息从消息队列中取出。
首先分析消息,通过消息的参数判断该消息对应的Handler,
然后将消息分发到指定的Handler进行处理。
欧了!!!!!!!!!!!!!!!!