Handler
定义:接收子线程发送过来的一些信息和带有消息队列的进程对象,从而在主线程中进行的相应的操作。
作用:
- 定时执行Message和MessageQueue
- 让一个动作在不同线程中执行
常用方法:
发送消息
//post(Runnable)
// postAtTime(Runnable,long)
// postDelayed(Runnable,long)
post是处理Runnable对象;
// sendEmptyMessage(int)
// sendMessage(Message);
// sendMessageAtTime(Message,long)
// sendMessageDelayed(Message,long)接收消息
handleMessage(Message msg); 子类必须重写此方法,处理消息
一个使用handler来实现一个倒计时的按钮:
public class HandlerButtonActivity extends Activity { private static final int Message_Code=8888888; private TextView textView; private TextHandler textHandler=new TextHandler(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.handlerbutton); textView = (TextView) findViewById(R.id.text01); Message message=textHandler.obtainMessage();//最好不要用new Handler因为不便于销毁 message.arg1=0; message.arg2=1; message.what= Message_Code; message.obj=10000; textHandler.sendMessageDelayed(message,1000);//延迟1s发送消息 } public TextView getTextView(){ return textView; } public static class TextHandler extends Handler{ public final WeakReference mHandlerbuttonActivityWeakReference; public TextHandler(HandlerButtonActivity activity){ mHandlerbuttonActivityWeakReference=new WeakReference(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); HandlerButtonActivity handlerButtonActivity=mHandlerbuttonActivityWeakReference.get();//弱引用对象 switch (msg.what){ //接受消息 case Message_Code: int value= (int) msg.obj; handlerButtonActivity.getTextView().setText(String.valueOf(value/1000)); msg=Message.obtain(); msg.arg1=0; msg.arg2=1; msg.what= Message_Code; msg.obj=value-1000; if(value>0) sendMessageDelayed(msg,1000); break; } } } }
老师在视频中说使用弱引用可以避免内存泄漏的问题,因为当activity被销毁时,Handler所传递的Message对象存在于消息对列中,不会随着activity销毁而销毁。
Looper和MessageQueue
Looper:消息泵,就是不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper;
MessageQueue:消息队列,用来存放Handler发送过来的消息;
Android 系统的消息队列都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper)。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();//给线程创建一个消息循环
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();//使消息循环起作用,从消息队列里取消息,处理消息
}
}
在其他人的资料中,找到一些有用的东西:
Looper.loop()之后的代码不会被立即执行,当调用后 mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。Looper对象通过MessageQueue 来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。
Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper);