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

「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...

你可能感兴趣的:(android)