1.handler的作用是什么
1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器
2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面
2.Handle、 Looper 、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 。
每一个线程里可含有一个Looper 对象以及一个MessageQueue 数据结构。在你的应用程序里,可以定义Handler 的子类别来接收Looper 所送出的消息。
3.主线程里面定义两个不同的handler实例,其中一个handler发出的消息另外一个能接收到吗?
不能,虽然主线程共享同一个消息队列,但是它们通过message的what变量来区分到底是由哪一个handler发出的消息。Handler实例与消息处理是关联的,发送和接收要匹配
mainHandler2 = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);//这里接收不到
Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler2 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show() ;
}
} ;
mainHandler1 = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);//这里能接收到
Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler1 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show() ;
}
} ;
//Handler Lab1
findViewById(R.id.buttonHandlerLab1).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
mainHandler1.sendMessage(defineNewMessage("Lab1")) ;
//try to use mainHanlder2 to send meesage and receive .
//mainHandler2.sendMessage(defineNewMessage("Lab1")) ;
}
}).start() ;
}
}) ;
4.任何一个线程都有消息队列吗
默认只有主线程才有消息队列,自己新建的普通线程是没有线程队列的。不过子线程中用HandlerThread,默认有消息队列
1)//下面代码会抛出Can't create handler inside thread that has not called Looper.prepare()异常
findViewById(R.id.buttonHandlerLab2).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
Handler lab2Handler = new Handler() ;
lab2Handler.sendMessage(defineNewMessage("Lab2")) ;
}
}).start() ;
}
}) ;
2)下面的代码是正确的
class SubHandlerThread extends HandlerThread{
public SubHandlerThread(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void run() {
// TODO Auto-generated method stub
ProcessCaculate() ;
Looper lp = this.getLooper() ;
new Handler(lp){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message by HandlerThread "+ msg.getData().getString(HANDLER_KEY)) ;
}
}.sendMessage(defineNewMessage("Lab2.2")) ;
}
}
findViewById(R.id.buttonHandlerLab3).setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stub//using HandlerThread to make handler (message queue) ,send messageSubHandlerThread subHandlerThread = new SubHandlerThread("threadone"); subHandlerThread.start();}}) ;
5.子线程的handler可以使用主线程的消息队列吗
可以的。
//Handler Lab3.1 child thread get main thread's looper and send message .
findViewById(R.id.buttonHandlerLab4).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Handler lab3Handler ;
lab3Handler = new Handler(Looper.getMainLooper())
{
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message: "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler") ;
}
};
lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
}
}).start() ;
}
}) ;
5.子线程的handler可以使用子线程的消息队列吗
//Handler Lab3.2 using looper.prepare() and looper.loop() .
findViewById(R.id.buttonHandlerLab5).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
Looper.prepare();//实例化looper对象,生成消息队列
lab3Handler = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message from "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler") ;
}
} ;
lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
Looper.loop() ;//循环消息队列
}
}).start() ;
}
}) ;
总结:
1.Handler实例与消息处理是关联的,发送和接收要匹配。
2.Handler操作队列,主要是在子线程操作主线程消息队列
3.子线程默认是没有消息队列的
1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器
2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面
2.Handle、 Looper 、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 。
每一个线程里可含有一个Looper 对象以及一个MessageQueue 数据结构。在你的应用程序里,可以定义Handler 的子类别来接收Looper 所送出的消息。
3.主线程里面定义两个不同的handler实例,其中一个handler发出的消息另外一个能接收到吗?
不能,虽然主线程共享同一个消息队列,但是它们通过message的what变量来区分到底是由哪一个handler发出的消息。Handler实例与消息处理是关联的,发送和接收要匹配
mainHandler2 = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);//这里接收不到
Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler2 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show() ;
}
} ;
mainHandler1 = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);//这里能接收到
Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler1 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show() ;
}
} ;
//Handler Lab1
findViewById(R.id.buttonHandlerLab1).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
mainHandler1.sendMessage(defineNewMessage("Lab1")) ;
//try to use mainHanlder2 to send meesage and receive .
//mainHandler2.sendMessage(defineNewMessage("Lab1")) ;
}
}).start() ;
}
}) ;
4.任何一个线程都有消息队列吗
默认只有主线程才有消息队列,自己新建的普通线程是没有线程队列的。不过子线程中用HandlerThread,默认有消息队列
1)//下面代码会抛出Can't create handler inside thread that has not called Looper.prepare()异常
findViewById(R.id.buttonHandlerLab2).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
Handler lab2Handler = new Handler() ;
lab2Handler.sendMessage(defineNewMessage("Lab2")) ;
}
}).start() ;
}
}) ;
2)下面的代码是正确的
class SubHandlerThread extends HandlerThread{
public SubHandlerThread(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void run() {
// TODO Auto-generated method stub
ProcessCaculate() ;
Looper lp = this.getLooper() ;
new Handler(lp){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message by HandlerThread "+ msg.getData().getString(HANDLER_KEY)) ;
}
}.sendMessage(defineNewMessage("Lab2.2")) ;
}
}
findViewById(R.id.buttonHandlerLab3).setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stub//using HandlerThread to make handler (message queue) ,send messageSubHandlerThread subHandlerThread = new SubHandlerThread("threadone"); subHandlerThread.start();}}) ;
5.子线程的handler可以使用主线程的消息队列吗
可以的。
//Handler Lab3.1 child thread get main thread's looper and send message .
findViewById(R.id.buttonHandlerLab4).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Handler lab3Handler ;
lab3Handler = new Handler(Looper.getMainLooper())
{
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message: "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler") ;
}
};
lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
}
}).start() ;
}
}) ;
5.子线程的handler可以使用子线程的消息队列吗
//Handler Lab3.2 using looper.prepare() and looper.loop() .
findViewById(R.id.buttonHandlerLab5).setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable(){
@Override
public void run() {
Looper.prepare();//实例化looper对象,生成消息队列
lab3Handler = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message from "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler") ;
}
} ;
lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
Looper.loop() ;//循环消息队列
}
}).start() ;
}
}) ;
总结:
1.Handler实例与消息处理是关联的,发送和接收要匹配。
2.Handler操作队列,主要是在子线程操作主线程消息队列
3.子线程默认是没有消息队列的