关于android:Android基于轻量级Messenger的进程通信

9次阅读

共计 3460 个字符,预计需要花费 9 分钟才能阅读完成。

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

正文完
 0