「Android」基于轻量级Messenger的过程通信

Android中目前存在多种IPC形式,别离为:

  • Bundle
  • 文件共享
  • Messenger
  • AIDL
  • ContentProvider
  • Socket

Messenger

Messenger是一种轻量级的IPC计划,它的底层实现是基于AIDL:

    /**     * Create a new Messenger pointing to the given Handler.  Any Message     * objects sent through this Messenger will appear in the Handler as if     * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had     * been called directly.     *      * @param target The Handler that will receive sent messages.     */    public Messenger(Handler target) {        mTarget = target.getIMessenger();    }    /**     * Create a Messenger from a raw IBinder, which had previously been     * retrieved with {@link #getBinder}.     *      * @param target The IBinder this Messenger should communicate with.     */    public Messenger(IBinder target) {        mTarget = IMessenger.Stub.asInterface(target);    }

Messenger对AIDL做了封装,使得咱们能够更简便的进行过程通信。同时,它一次解决一个申请,不存在并发执行的情景,因而在服务端不须要思考线程同步问题。

Messenger原理图

实现一个Messenger次要分为Server端和Client端:

  1. Server端
    须要在Server端创立一个Service来解决Client端的连贯申请,同时创立一个Handler对象并通过它来创立一个Messenger对象,而后在Service的onBind中()办法返回这个Messenger对象底层的Binder。
  2. Client端
    首先须要绑定Server端的Service,绑定胜利后即可获取到Server端返回的IBinder对象并通过它创立一个Messenger对象,通过这个Messenger对象就能够向Server端发送音讯,发消息的类型为Message对象。
    如果须要Server端回应Client端,如同Server端一样,Client端也须要创立一个Handler对象并通过它来创立一个Messenger对象,并把这个Messenger对象通过Message的replyTo参数传递给Server端。
    Server端可通过这个replyTo参数获取到Client端的Messenger对象,并通过这个Messenger对象就能够向Client端发送音讯

Server端示例代码

public class MessengerService extends Service {    private static class ServerMessengerHandler extends Handler {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MSG_FROM_CLIENT:                    // 通过Message,获取Client端的Messenger对象                    mClientMessenger = msg.replyTo;                    Message replyMessage = Message.obtain(null, MSG_FROM_SERVER);                    Bundle bundle = new Bundle();                    // 将data,增加进Message                    bundle.putString(DATA, DATA);                    replyMessage.setData(bundle);                    try {                        // 向Client端发送Message                        mClientMessenger.send(replyMessage);                    } catch (RemoteException e) {                        e.printStackTrace();                    }                    break;            }        }    }    private final Messenger mServerMessenger = new Messenger(new ServerMessengerHandler());    private Messenger mClientMessenger;    @Override    public IBinder onBind(Intent intent) {        return mServerMessenger.getBinder();    }}

Client端示例代码

public class MessengerClient extends Context{    private static class ClientMessengerHandler extends Handler {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MSG_FROM_SERVER:                    // 获取data                    String data = msg.getData().getString(DATA);                    break;            }        }    }    private boolean mBound;    private final Messenger mClientMessenger = new Messenger(new ClientMessengerHandler());    private Messenger mServerMessenger;    private ServiceConnection mConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            // 通过IBinder对象,获取Server端的Messenger对象            mServerMessenger = new Messenger(service);            mBound = true;            Message requestMessage = Message.obtain(null, MSG_FROM_CLIENT);            Bundle bundle = new Bundle();            bundle.putString(REQUEST, REQUEST);            requestMessage.setData(bundle);            // 将Client端的Messenger对象,增加进Message            mClientMessenger = new Messenger(mHandler);            requestMessage.replyTo = mClientMessenger;            try {                // 向Server端发送Message                mServerMessenger.send(msg);            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName name) {            mServerMessenger = null;            mBound = false;        }    }    // 申请data    // Client端触发基于Messenger的IPC流程    private void doBindService() {        Intent intent = new Intent(this, MessengerServer.class);        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);    }}

IPC形式的优缺点和实用场景

形式能力特点实用场景
AIDL反对一对多并发通信、反对实时通信、反对跨过程函数调用须要独立定义.aidl标准、须要增加.aidl文件、应用较简单一对多即时通信,有RPC需要
Messenger反对一对多串行通信、反对实时通信、反对Bundle传递无需独立定义.aidl标准、无需增加.aidl文件、应用较简洁低并发的一对多即时通信,无返回后果的RPC需要

参考

https://developer.android.goo...
https://developer.android.goo...