先来看一个例子:
public class MainActivity extends Activity {
private TextView textView;
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
System.out.println("Clicked .. "+ Thread.currentThread().getName());
Bundle bundle = new Bundle();
bundle.putInt("age", 23);
bundle.putString("name", "han");
Message msg = handler.obtainMessage();
msg.setData(bundle);
handler.sendMessage(msg);
}
});
WorkerThread wt = new WorkerThread();
wt.start();
}
class WorkerThread extends Thread{
@Override
public void run() {
Looper.prepare();
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("WorkerThread name : "+Thread.currentThread().getName());
System.out.println("在"+Thread.currentThread().getName()+"线程中进行处理费时的操作..");
System.out.println("age : " + msg.getData().getInt("age") + " name : " + msg.getData().getString("name"));
}
};
Looper.loop();
}
}
}
下面是运行的效果:
System.out: Clicked .. main
System.out: WorkerThread name : Thread-4872
System.out: 在Thread-4872线程中进行处理费时的操作..
System.out: age : 23 name : han
OK,下面切入正题!
在android开发中,handler主要是为了实现线程(MainThread、WorkerThread)间的消息传递,google将其设计的很巧妙,刚开始接触总是感觉云里雾里,下面通过源代码窥探其中的原理,如有错误不妥,还望大神指正。
先看我们程序中使用handler的一般写法(在Looper.java源代码中也有):
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.java的部分源代码,仅贴出对理解有帮助的行:
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;
final MessageQueue mQueue;
final Thread mThread;
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "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.recycleUnchecked();
}
}
public static Looper myLooper() {
return sThreadLocal.get();
}
public static MessageQueue myQueue() {
return myLooper().mQueue;
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
下面再贴出Handler.java的部分源代码:
public class Handler {
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
}
现在我们从前往后梳理,其实这中间主要用到一个ThreadLocal类,它通过set、get方法设置和得到与当前线程相关的局部变量,此处为Looper,不懂的童鞋请前往这里。通过ThreadLocal类,以及Looper、Handler中成员变量的赋值,建立了Looper和Handler的联系。
Looper.prepare();
在Looper.java中,我们看到,在调用prepare()方法时,创建了一个Looper对象(创建Looper对象时创建了MessageQueue对象,并将其放到成员变量mQueue中),并将该对象放到ThreadLocal(即当前线程中有一个Looper对象)中。
mHandler = new Handler()
在Handler.java中,我们看到,构造方法在调用时,调用Looper.myLooper()方法,得到当前线程中的Looper对象,赋值给Handler的成员变量mLooper,同时从当前线程中的Looper(即Handler.mLooper)中取得MessageQueue(即Looper.mQueue),赋值给Handler的成员变量mQueue。至此,Looper和Handler的联系便已经建立起来了。先总结下:一个Looper对象对应一个线程,同时也对应一个Handler,Looper和Handler对应的MessageQueue是同一个。
接下来,Looper.loop();
从源代码中我们可以看到,调用myLooper()方法,得到当前线程中Looper对象,进而取得与Looper对应的MessageQueue对象,赋值给queue,进入for循环,从消息队列中取得待处理的Message对象msg(这个过程可能会被阻塞),接下来msg.target.dispatchMessage(msg),在这里,msg.target是个什么东西呢?在程序中,我们一般会这么写:
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
首先,我们先看下Hander.obtainMessage()方法:
public final Message obtainMessage()
{
return Message.obtain(this);
}
可以看到,这里调用了Message.obtain(this)方法,而this指的是掉用该方法的对象,按照上述我们一般的写法,即handler.再看Message.obtain(Handler h)方法:
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
Message类的成员变量我们此时来看下:
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
public Messenger replyTo;
public int sendingUid = -1;
static final int FLAG_IN_USE = 1 << 0;
static final int FLAG_ASYNCHRONOUS = 1 << 1;
static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
int flags;
long when;
Bundle data;
Handler target;
Runnable callback;
Message next;
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
private static boolean gCheckRecycle = true;
此处重点注意下target成员变量,可以看到该成员变量是一个Handler类型的,所以msg.target指的就是生成该消息对象的Handler对象。再看Handler.dispatchMessage(Message msg)方法:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
该方法中handleMessage方法就是需要我们来写的逻辑代码。
另外这篇文章写得也挺不错,大家可以参考下。http://blog.csdn.net/guolin_blog/article/details/9991569
以下附上我练习的代码:
Ⅰ、演示Handler初步认识
public class MainActivity extends Activity {
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
handler = new FirstHandler();
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Message msg = handler.obtainMessage();
msg.what = 88;
handler.sendMessage(msg);
//上面一行代码将消息对象放置到消息队列中
//1、Looper将会从消息队列中将消息对象取出
//2、Looper将会找到与消息对象对应的Handler对象
//3、Looper将会调用handler对象的hanleMessage(Message msg)方法,用于处理消息对象
}
});
}
class FirstHandler extends Handler {
@Override
public void handleMessage(Message msg) {
System.out.println("what : " + msg.what);
}
}
}
Ⅱ、演示在WorkerThread处理业务并在MainThread更新UI
public class MainActivity extends Activity {
private Button button;
private Handler handler;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new MyHandler();
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Thread wt = new WorkerThread();
wt.start();
}
});
}
class WorkerThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Message msg = handler.obtainMessage();
msg.obj = "data from the Internet...";
handler.sendMessage(msg);
}
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
String s = (String) msg.obj;
textView.setText(s);
}
}
}
Ⅲ、从MainThread向WorkerThread中发送消息
public class MainActivity extends Activity {
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Message msg = handler.obtainMessage();
System.out.println("onClick:"+Thread.currentThread().getName());
handler.sendMessage(msg);
}
});
Thread thread = new WorkerThread();
thread.start();
}
class WorkerThread extends Thread{
@Override
public void run() {
Looper.prepare();
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("WorkerThread:"+Thread.currentThread().getName());
System.out.println("消息来啦...");
}
};
Looper.loop();
}
}
}
下面是post方法的使用:
public class MainActivity extends Activity {
private TextView textView;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textView);
handler = new Handler();
new Thread(){
public void run() {
try {
Thread.sleep(1000);
handler.post(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName());
textView.setText("update Thread...");
};
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
}.start();
}
}
更新UI,输出结果,打印的线程名字是 main!是不是很诧异.我们看下post方法源代码:
Handler.java
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
看到这里,结合上面的dispatchMessage方法,
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
此处直接执行了handleCallback(msg)方法.
private static void handleCallback(Message message) {
message.callback.run();
}
message.callback正是我们定义的Runnable对象,直接调用了它的run()方法.由于处理该方法的Looper是在MainThread中生成的,所以虽然从代码上看启用了一个新线程,但还是在UIThread中执行的,所以会进行更新UI的操作,不会报ANR错误.
另外一个例子:
public class HandlerActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button b1 = (Button)findViewById(R.id.button1);
Button b2 = (Button)findViewById(R.id.button2);
b1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//立即把线程加入消息队列中
handler.post(r);
}
});
b2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//停止线程
handler.removeCallbacks(r);
}
});
}
Handler handler = new Handler();
/**
*该方法的内部类将在handler.sendMessage(msg)后执行
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("msg:"+msg.arg1);
}
};
*/
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("sysout Thread");
//得到一个消息对象,Message类是有Android系统
Message msg = handler.obtainMessage();
//将msg对象arg1参数设置为122,用arg1和arg2传递消息
//优点是系统资源消耗较小
msg.arg1 = 122;
//将消息加入到另外一个消息队列中去
handler.sendMessage(msg);
//3000毫秒后加入线程到消息队列中
handler.postDelayed(r, 3000);
}
};
}
以下再演示一个postDelayed()的例子:
public class MainActivity extends Activity {
private TextView textView;
private ImageView imgView;
private int index;
private Handler handler = new Handler();
int[] imgs = {R.drawable.p1,R.drawable.p2,R.drawable.p3};
class MyRunnable implements Runnable{
@Override
public void run() {
index++;
index = index%3;
imgView.setImageResource(imgs[index]);
handler.postDelayed(this, 1000);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textView);
imgView = (ImageView) findViewById(R.id.imageView);
//new Thread(new MyRunnable()).start();
handler.post(new MyRunnable());
}
}
程序启动后,每隔一秒会更新图片。
下面是Handler的另一种构造方法的事例:
public class MainActivity extends Activity {
private Button button;
private Handler handler = new Handler(new Callback() {
@Override
public boolean handleMessage(Message arg0) {
Toast.makeText(getApplicationContext(), ""+1, 1).show();
<strong>return true;</strong>
}
}){
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), ""+2, 1).show();
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
handler.sendEmptyMessage(1);
}
});
}
}
当黑体部分返回true时,不会执行Handler的 public void handleMessage(Message msg)方法,当黑体部分返回假时,才会执行我们重写的handler的handleMessage方法。让我们看下源代码。Callback其实是Handler的一个内部接口:
Handler$Callback.class
public interface Callback {
public boolean handleMessage(Message msg);
}
再结合上面提到的Handler的构造方法:
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
还有
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
可以看到其中的玄机。所以,我们可以在构造Handler时重写Callback的handleMessage方法来起到一个过滤的作用,对符合条件的消息返回false进行处理。
下面再来看看HandlerThread的用法。例子:
public class MainActivity extends Activity {
private TextView text;
private Handler handler;
private HandlerThread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
text = new TextView(this);
text.setText("handler Thread...");
setContentView(text);
thread = new HandlerThread("ThreadName...");
thread.start();
handler = new Handler(thread.getLooper()){
@Override
public void handleMessage(Message msg) {
System.out.println("当前线程名称:"+Thread.currentThread().getName());
}
};
handler.sendEmptyMessage(1);
}
}
程序运行后,输出:当前线程名称:ThreadName...
HandlerThread就是一个线程,它继承Thread类,我们看看它的run()方法:
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
getLooper()方法:
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();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
利用HandlerThread类可以更好的帮助我们实现线程的操作。
补充一点,handler.sendMessage()将Message发送到消息队列中,其中的handler就要将来处理Message的Handler,和Message.sendToTarget一样。