package envi.handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
public class HandlerTest4 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//得到当前线程也就是Activity的线程ID,并打印出来
System.out.println(Thread.currentThread().getId());
//生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能
HandlerThread handlerThread = new HandlerThread("handler thread");
//启动handlerThread线程,在使用HandlerThread的getLooper()之前,必须先
//启动handlerThread类的start()
handlerThread.start();
// myHandler对象从handlerThread中得到Looper
MyHandler myHandler = new MyHandler(handlerThread.getLooper());
Message msg = myHandler.obtainMessage();
//msg.obj = "123";
//使用Bundle向handler对象发送消息,Bundle存放String键值对的mapping
Bundle bundle = new Bundle();
bundle.putInt("age", 20);
bundle.putString("name","Jim");
bundle.putString("address", "USA");
msg.setData(bundle);
//msg.setData(data);
//将msg发送到目标对象,这个目标对象是handler
msg.sendToTarget();
}
// MyHandler类继承Handler类
class MyHandler extends Handler{
public MyHandler(){
}
public MyHandler(Looper looper){
//继承父类的构造函数,参数是looper对象
super(looper);
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
//super.handleMessage(msg);
//String s = (String)msg.obj;
//从消息队列中获取msg信息
Bundle bundle = msg.getData();
int age = bundle.getInt("age");
String name = bundle.getString("name");
String address = bundle.getString("address");
//打印获取msg信息
System.out.println("age is " + age +", name is" + name + ", address is" + address);
//得到当前线程即handler线程的ID,并打印,与上一次打印线程ID号不一样
System.out.println("handler---" + Thread.currentThread().getId());
System.out.println("handlerMessage");
}
}
}
接下来,依次来看看Handler,Looper, HandlerThread类。
在此之前,先谈谈Andriod应用程序与消息。和Windows等一样,都是用消息驱动来完成的。大致原理如下 :
1. 往消息队列里发送消息
2. 使用消息循环,从消息队列中取出消息,然后处理。
在Android系统中,主要Handler和Looper来实现的。Handler类,它负责消息发送,获取消息,消息处理等功能;Looper类,它有一个消息队列,负责消息循环。
Handler类分析
先看它的成员变量:
final MessageQueue mQueue;//有一个消息队列
final Looper mLooper;//有一个Looper
final Callback mCallback;//有一个回调类
IMessenger mMessenger;//消息对象
在看看它的构造函数:
1.
public Handler() {
//获取线程的Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//得到Looper的消息队列
mQueue = mLooper.mQueue;
//设置回调null
mCallback = null;
}
2.
public Handler(Callback callback) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
//设置回调callback
mCallback = callback;
}
3.
public Handler(Looper looper) {
mLooper = looper;//外部传进来的不确定的Looper
mQueue = looper.mQueue;
mCallback = null;
}
4.
public Handler(Looper looper, Callback callback) {
mLooper = looper;
mQueue = looper.mQueue;
//设置回调callback
mCallback = callback;
}
通过这些构造函数,会发现,Handler类中的mQueue(消息队列)是由Looper类提供的。
下面来关注下Handler类中的消息操作方法。有一些API:
public final Message obtainMessage(int what);//创建消息
public final boolean sendMessage(Message msg);//发送消息,该消息添加到队列尾部
public void dispatchMessage(Message msg);//消息处理
分析sendMessage方法:
Step1:
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);//调用Step2,delay时间为0
}
Step2:
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); //调用Step3,算上当前时间,uptimeMillis是绝对时间
}
Step3:
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
//this是指把自己设置为target,加入消息队列中
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);// 通过enqueueMessage加入消息队列
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
分析dispatchMessage方法:
Step1:
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
//如果传进来的Message带有回调callback,由callback处理消息
if (msg.callback != null) {
handleCallback(msg);
} else {
//如果Handler构造函数设置了回调mCallback,由mCallback处理消息
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//交给子类
}
}
Step2:
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}//子类实必须现接受消息方法
Looper类分析
在Looper类前,Android提供了一个例子:
class LooperThread extends Thread {
public Handler mHandler;
//实现LooperThread的run()方法
public void run() {
//先准备
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
//handler消息处理
// process incoming messages here
}
};
//消息循环
Looper.loop();
}
}
然后通过LooperThread的start()启动线程。
先看成员变量:
// sThreadLocal.get() will return null unless you've called prepare().
private static final ThreadLocal sThreadLocal = new ThreadLocal();//线程局部变量
final MessageQueue mQueue;//消息队列
volatile boolean mRun;//布尔变量,记录运行与否
Thread mThread;//一个线程类
private Printer mLogging = null;//打印信息接口
private static Looper mMainLooper = null;//主Looper类
成员函数:
1. prepare函数
public static final void prepare() {
//只能一次调用prepare
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//先通过new Looper()创建匿名对象,然后将其设置到该线程的局部变量中
sThreadLocal.set(new Looper());
}
2. myLooper函数
public static final Looper myLooper() {
//从当前线程里返回其局部变量中的Looper对象,也就是prepare()中创建的Looper
return (Looper)sThreadLocal.get();
}
3.构造函数
private Looper() {
//创建消息队列
mQueue = new MessageQueue();
//设置运行态为true
mRun = true;
//获取当前线程的对象
mThread = Thread.currentThread();
}
4.Looper循环
public static final void loop() {
Looper me = myLooper();//从当前线程里返回其局部变量中的Looper对象
MessageQueue queue = me.mQueue;//得到Looper对象的消息队列
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
//确保是本地线程的身份,通过Binder追踪远端代理线程的真实身份
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
while (true) {
//进入消息循环,取出消息队列中下一个要处理的消息
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
// Message的对象有一个target,见前面Handler类分析,它是Handler类型,为空的话,就退出消息循环
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
//打印信息
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
//调用Handler类的成员函数dispatchMessage(Message msg)
msg.target.dispatchMessage(msg);
//打印信息
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
//确保dispatching时候本地的当前线程身份不被破坏
final long newIdent = Binder.clearCallingIdentity();
//二者不等,Thread identity changed
if (ident != newIdent) {
Log.wtf("Looper", "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
}
HandlerThread分析
它的主要作用是解决Handler和Looper的同步关系。
成员函数:
1.构造函数
public HandlerThread(String name, int priority) {
super(name);//调用父类方法
mPriority = priority;//优先级
}
2. getLooper
结合开始的应用程序来说明:
//在Activity线程里调用getLooper来获取Handler线程的Looper
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();//如果Handler(新线程)还没有创建Looper,等待
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
3. run函数
public void run() {
mTid = Process.myTid();//线程ID
Looper.prepare();//在这个线程上创建Looper
synchronized (this) {
mLooper = Looper.myLooper();//从当前线程里返回其局部变量中的//Looper对象
notifyAll();//通知要取Looper的线程,在Handler线程的Looper已经创建好
}
Process.setThreadPriority(mPriority);//设置线程优先权
onLooperPrepared();//在Loop循环前的一些设置
Looper.loop();//Loop循环
mTid = -1;
}
说明:在android开发文档的Thread类里,有这样的说明:
1. Calls the run()
method of the Runnable object the receiver holds. If no Runnable is set, does nothing.
2. Starts the new Thread of execution. The run()
method of the receiver will be called by the receiver Thread itself (and not the Thread callingstart()
).
上面的应用程序并没有实现Runnable接口,所以没有复写run()方法,而是复写start()方法。复写start()方法,会启用一个新的线程;而用实现Runnable接口,复写run()方法,它和当前线程即上面的Activity共用同一线程。