Messeger适用于跨进程通信时不需多线程交互的情况。如若需要跨进程多线程交互,可以使用AIDL(请看《Android进程间通信(二):AIDL》)。
一、可运行代码类(Runnable)
public interface Runnable
{
/**
* 把需要运行的代码放在这个方法中
*/
public void run();
}
二、线程类(Thread类)
public class Thread implements Runnable
{
/**
* 用来保存构造时传入的Runnable对象
*/
Runnable target;
/**
* 常用的构造方法。另外还有其他构造方法
*/
public Thread(Runnable runnable)
{
// 最终会使得target = runnable;
...
}
/**
* 如果直接调用此方法,是不会创建新线程的,而是在当前线程中执行这段代码
*/
public void run()
{
if (target != null)
{
target.run();
}
}
/**
* 这个方法会真正创建一个新线程,并调用run()
*/
public synchronized void start() { ... }
...
}
三、消息(Message)
public final class Message implements Parcelable
{
/**
* 自定义的消息内容。
*/
public int what;
public int arg1;
public int arg2;
public Object obj;
Bundle data;
public void setData(Bundle data) {
this.data = data;
}
public Bundle getData() {
if (data == null) {
data = new Bundle();
}
return data;
}
/**
* 若这个成员不为null,默认的Handler实现是
* 只调用它的run方法处理本消息
*/
Runnable callback;
public Runnable getCallback() {
return callback;
}
/**
* 这个成员可以不设置:
* 在本消息被Handler对象加入消息队列之前,
* 或者在调用Handler对象的obtainMessage方法之后,
* 它都会被设置为该Handler对象。
*/
Handler target;
/**
* 从系统维护的全局消息池中获取一个新的消息对象。比直接构造一个新消息更节省资源
*/
public static Message obtain(/* 本方法有多种重载版本 */) { ... }
/**
* 若本消息是调用Handler对象的obtainMessage方法来获取的,
* 或者手动地设置了target成员,则可调用此方法
*/
public void sendToTarget()
{
target.sendMessage(this);
}
// ==================== 进程间通信的分割线 ==================== //
/**
* 本消息应该回复给哪个信使(Messenger)。
* 如果希望对方回复,则需在发信前,设置好这个成员
*/
public Messenger replyTo;
/**
* 发信者的用户ID。当本消息通过信使发送时,这个值会被自动设置
*/
public int sendingUid = -1;
...
}
四、消息队列(MessageQueue)
public final class MessageQueue
{
/**
* 把一个消息加入队列
*/
boolean enqueueMessage(Message msg, long when) { ... }
/**
* 获取消息队列中的下一个消息
*/
Message next()
{
/**
* 本方法的策略:
* 1.当调用了quit()之后,返回null;
* 2.当有队列中有非延时或者已到期的消息时,返回首个该类型的消息;
* 3.阻塞。
*/
...
}
/**
* 参数为false时,不管当前消息队列是否有消息,删除所有消息;
* 参数为true时,删除未到期的消息
*/
void quit(boolean safe) { ... }
...
}
五、消息泵(Looper)
public final class Looper
{
/**
* 系统会为每个应用的主线程创建一个主Looper对象——sMainLooper。
* 另外还有一个静态成员变量保存着各个线程中的Looper对象(一个线程只能拥有一个Looper),
* sMainLooper是其中之一。
*/
private static Looper sMainLooper;
/**
* 每个Looper对象中都维护着一个消息队列
*/
final MessageQueue mQueue;
/**
* 如果要在非主线程中创建Looper对象,需先调用这个方法,
* 再创建处理消息的Handler对象,最后调用loop()
*/
public static void prepare()
{
// 最终会创建一个消息队列作为内部成员
...
}
/**
* 获取主Looper对象
*/
public static Looper getMainLooper()
{
synchronized (Looper.class)
{
return sMainLooper;
}
}
/**
* 获取当前线程的Looper
*/
public static Looper myLooper() { ... }
/**
* 如果要在非主线程中创建Looper对象,需先调用prepare(),
* 再创建处理消息的Handler对象,最后调用此方法。
* 这个方法会一直循环地去当前线程的Looper对象的消息队列中取消息
*/
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;
...
for (;;)
{
// 获取下一个消息。可能会阻塞
Message msg = queue.next();
if (msg == null)
{
// 若没有消息,则表明已调用了quit(),所以退出循环
return;
}
...
// 派发消息。实际上是交回给发送消息的Handler对象处理消息
msg.target.dispatchMessage(msg);
...
// 回收消息,放回全局消息池中
msg.recycleUnchecked();
}
}
/**
* 不管当前消息队列是否有消息,舍弃所有消息,直接退出循环
*/
public void quit()
{
mQueue.quit(false);
}
/**
* 派发非延时及已到期的消息给Handler,而未到期的消息将会被舍弃
*/
public void quitSafely()
{
mQueue.quit(true);
}
...
}
六、消息处理者(Handler)
public class Handler
{
/**
* 指定为某个线程的Looper或者设置为当前线程的Looper
*/
final Looper mLooper;
/**
* 设置为mLooper中的MessageQueue
*/
final MessageQueue mQueue;
public Handler(/* 本方法有多种重载版本 */)
{
/**
* 若不指定Looper则默认与当前线程的Looper绑定:mLooper = Looper.myLooper();
* 而消息队列成员则与Looper对象的等同:mQueue = mLooper.mQueue;
*/
...
}
/**
* 从系统维护的全局消息池中获取一个新的消息对象。比直接构造一个新消息更节省资源
*/
public final Message obtainMessage(/* 本方法有多种重载版本 */)
{
return Message.obtain(/* 本方法有多种重载版本 */);
}
/**
* 以下7个send系列方法最终都会调用enqueueMessage()来发送消息
*/
public final boolean sendMessage(Message msg) { ... }
public final boolean sendEmptyMessage(int what) { ... }
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { ... }
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { ... }
public final boolean sendMessageDelayed(Message msg, long delayMillis) { ... }
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { ... }
public final boolean sendMessageAtFrontOfQueue(Message msg) { ... }
/**
* 以下5个post系列方法,都会把参数封装到一个Message对象中,
* 并且最终调用enqueueMessage()来发送消息
*/
public final boolean post(Runnable r) { ... }
public final boolean postAtTime(Runnable r, long uptimeMillis) { ... }
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { ... }
public final boolean postDelayed(Runnable r, long delayMillis) { ... }
public final boolean postAtFrontOfQueue(Runnable r) { ... }
/**
* 以上的post系列和send系列方法最终会调用到这个方法
*/
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
{
/**
* 无论用哪个Handler对象来发消息,最终都会派发回给该Handler处理。
* 由此可见,若要发消息给某个线程的Handler对象,需要获取到该对象,
* 用它来发消息,并且消息的target成员不必设置
*/
msg.target = this;
...
/**
* 把消息放入消息队列中。
* 参数queue实际上就是mLooper
*/
return queue.enqueueMessage(msg, uptimeMillis);
}
/**
* 派发消息
*/
public void dispatchMessage(Message msg)
{
if (msg.callback != null)
{
/**
* 1.当消息中的Runnable类型的callback成员不为null时,调用该成员的run方法。
* 这行代码相当于msg.callback.run();
*/
handleCallback(msg);
}
else
{
if (mCallback != null)
{
// 2.如果成员mCallback不为空时
if (mCallback.handleMessage(msg))
{
// 如果没有进一步处理的需要,直接返回
return;
}
}
// 3.常用的处理消息方法,需要我们实现其代码
handleMessage(msg);
}
}
/**
* 当消息中的Runnable类型的callback成员不为null时,调用此方法
*/
private static void handleCallback(Message message)
{
message.callback.run();
}
/**
* 通常在这里实现处理消息的代码
*/
public void handleMessage(Message msg)
{
/**
* 需要我们实现的处理消息代码。例如:
* switch(msg.what)
* {
* case CONDITION_ONE:
* // do something here
* break;
* case CONDITION_TWO:
* // do something here
* break;
*
* ...
* }
*/
}
/**
* 自定义处理消息的回调接口
*/
public interface Callback
{
// 如果没有进一步处理(即handleMessage())的需要,返回true,否则返回false
public boolean handleMessage(Message msg);
}
/**
* 可以在调用构造方法时,传入一个实现Callback接口的对象来设置这个成员
*/
final Callback mCallback;
// ==================== 进程间通信的分割线 ==================== //
/**
* 内部维护的信使接口对象
*/
IMessenger mMessenger;
/**
* 获取自身维护的信使接口对象
*/
final IMessenger getIMessenger()
{
synchronized (mQueue)
{
if (mMessenger != null)
{
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
/**
* mMessenger成员的类型实际上是这个MessengerImpl类
*/
private final class MessengerImpl extends IMessenger.Stub
{
/**
* 信使正是通过这个方法来发消息的
*/
public void send(Message msg)
{
// 保存调用者的用户ID
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
...
}
七、信使(Messenger)
public final class Messenger implements Parcelable
{
// ==================== 进程间通信的分割线 ==================== //
/**
* 这个信使接口成员,根据其指向的不同,有着不同的作用:
* 1.保存对方Handler的内部信使接口,用来发信给对方;
* 2.保存自己Handler的内部信使接口,供对方回信用。
* 如果是双向通信,则需要有两个信使对象,分别对应以上两种类型;
* 若只是单向通信,则只需前者
*/
private final IMessenger mTarget;
/**
* 保存自己Handler的内部信使接口,供对方回信用
*/
public Messenger(Handler target)
{
mTarget = target.getIMessenger();
}
/**
* 保存转为IBinder类型的对方Handler的内部信使接口,用来发信给对方
*/
public Messenger(IBinder target)
{
mTarget = IMessenger.Stub.asInterface(target);
}
/**
* 获取转为IBinder类型的(自己的)Handler的内部信使接口。可供对方回信用。
* 应用场景之一:
* 客户端绑定服务器的服务(Service),后者在onBind方法的中调用此方法返回:
* public IBinder onBind(Intent intent)
* {
* return myMessenger.getBinder();
* }
*/
public IBinder getBinder()
{
return mTarget.asBinder();
}
/**
* 给对方发消息
*/
public void send(Message message) throws RemoteException
{
// 如果希望对方回复,则需在发信前,设置好Message的replyTo成员
mTarget.send(message);
}
...
}
样例
public class MessengerService extends Service {
static final int MSG_DO_SOMETHING = 0x1;
class MessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_SOMETHING:
// Do something here
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger mMessenger = new Messenger(new MessageHandler());
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
...
}
public class MessengerActivity extends Activity {
Messenger mService = null;
boolean mBound;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
mBound = false;
}
};
public void doSomething(View v) {
if (!mBound) return;
Message msg = Message.obtain(null, MessengerService.MSG_DO_SOMETHING);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.XXX);
}
@Override
protected void onStart() {
super.onStart();
bindService(new Intent(this, MessengerService.class),
mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}