Android进程间通信之Messenger

本文例子中的完整代码已上传github:Messenger,如果对您有帮助,给个star吧,不胜感激~☺

Messenger 是基于消息(Message)的进程间通信方式。使用Messenger为服务创建接口,服务可以这种方式定义对应于不同类型Message对象的Handler,此Handler是Messenger的基础,Messenger随后可与客户端分享一个IBinder,从而让客户端能利用Message对象向服务发送命令。客户端还可以自定义Messenger来实现双向通信。

Messenger使用起来比AIDL更简单,如果对AIDL不了解,可以看下这篇:Android进程间通信之AIDL,Messenger的底层其实还是AIDL实现的,Messenger会将所有服务调用排入队列,依次调用;而AIDL接口会同时向服务发送多个请求,所以服务端必须处理好多线程。

Messenger使用步骤:

  1. 服务端创建一个Handler,用来接收客户端每个调用的回调
  2. Handler用于创建Messenger对象(对Handler的引用),在Handler中的 handleMessage()方法中处理客户端传过来的Message。
  3. Messenger创建一个IBinder,服务端通过onBind()方法使其返回客户端
  4. 客户端使用IBinder将Messenger(引用服务的Handler)实例化,然后使用后者将Message对象发送给服务端。
  5. 如果客户端想接收服务器的响应,则需要客户端也创建一个Messenger,当客户端收到ServiceConnection中的onServiceConnected()回调时,会向服务端发送一条Message,将客户端的Messenger赋值给Message的replyTo参数

下面举个栗子,先上效果图:


Android进程间通信之Messenger_第1张图片
messenger.gif

客户端代码:MessengerActivity.class

首先,编写Messenger准备接收服务器返回的信息:

Messenger messenger = new Messenger(new ClientHandler());

private class ClientHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
             //根据msg.what来区分服务器返回的不同信息
            case ServerThinking:
                showMessage("\n服务器正在绞尽脑汁的思考...");
                break;
            case MESS_FROM_SERVER:
                Bundle bundle = msg.getData();
                String responseInfo = bundle.getString(RESPONSE_KEY);
                if (!TextUtils.isEmpty(responseInfo)) {
                    showMessage("\n" + responseInfo, R.color.red_f);
                }
                break;
        }
    }
}

然后编写ServiceConnection类用来接收回调并向服务端发送Message:

private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //连接成功
            showMessage("\n连接远程服务端成功!", R.color.blue_color);
            isBound = true;
            mService = new Messenger(service);
            String question = "\n客户端:程序猿最讨厌皇帝的第几个儿子?";
            Message message = Message.obtain(null, MESS_FROM_CLIENT);
           //Messenger用来接收服务端发来的信息
            message.replyTo = messenger;
            try {
                //将Message发送到服务端
                mService.send(message);
                showMessage(question, R.color.red_f);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            //连接失败
            mService = null;
            isBound = false;
        }
    };

最后,绑定Service服务端:

Intent intent = new Intent();
intent.setAction("android.mq.messenger.service");
intent.setPackage("org.ninetripods.mq.multiprocess_sever");
bindService(intent, connection, BIND_AUTO_CREATE);

服务端代码:MessengerService.java

private HandlerThread thread;
private Handler serverHandler;
private Messenger messenger;

@Override
public void onCreate() {
    super.onCreate();
    //创建一个名字为my_thread的线程
    thread = new HandlerThread("my_thread");
    //启动一个线程
    thread.start();
    //在这个线程中创建一个handler
    serverHandler = new Handler(thread.getLooper()) {
       @Override
       public void handleMessage(Message msgFromClient) {
           super.handleMessage(msgFromClient);
           Message replyToClient = Message.obtain(msgFromClient);
             switch (msgFromClient.what) {
             //根据Message.what来判断执行服务端的哪段代码
                case MESS_FROM_CLIENT:
                   replyToClient.what = ServerThinking;
                     try {
                         Thread.sleep(1000);
                         //向客户端发送Message
                         msgFromClient.replyTo.send(replyToClient);
                         Thread.sleep(3 * 1000);
                        } catch (Exception e) {
                          e.printStackTrace();
                        }
                        replyToClient.what = MESS_FROM_SERVER;
                        Bundle bundle = new Bundle();
                        bundle.putString(RESPONSE_KEY, "服务器:我知道答案啦,是第八个儿子,因为他是八阿哥(bug)");
                        replyToClient.setData(bundle);
                        try {
                            //通过Bundle 封装数据并发送到客户端
                            msgFromClient.replyTo.send(replyToClient);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        break;
                }
            }
        };
        //构建一个Messenger
        messenger = new Messenger(serverHandler);
    }

    @Override
    public IBinder onBind(Intent intent) {
        //通过onBind()返回Binder实例供客户端调用
        return messenger.getBinder();
    }

最后别忘了声明Service:


    
        
        
    

代码看上去还是很简单的,完整代码已上传github:Messenger,如果对您有帮助,给个star吧,不胜感激~☺(注:项目中有两个项目,请确保先启动Server端,否则看不到效果)

你可能感兴趣的:(Android进程间通信之Messenger)