Messenger实现进程间通信

作者: 卖炭少年炭治郎 | 来源:发表于2020-05-19 12:05 被阅读0次

    为什么Messenger能进行进程间通信

    Messenger翻译为信使,他可以在不同的进程中传递Message对象

    1. 首先我们看下这个类的构造方法,发现,他的底层实现其实就是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);
        }
    

    我们在跟一下Handler的getIMessenger方法,发现就是我们所熟悉的aidl的写法。

    final IMessenger getIMessenger() {
            synchronized (mQueue) {
                if (mMessenger != null) {
                    return mMessenger;
                }
                mMessenger = new MessengerImpl();
                return mMessenger;
            }
        }
    
        private final class MessengerImpl extends IMessenger.Stub {
            public void send(Message msg) {
                msg.sendingUid = Binder.getCallingUid();
                Handler.this.sendMessage(msg);
            }
        }
    

    使用Messenger如何实现进程间通信

    1. 首先我们先写一个远程服务端
    public class MessengerService extends Service {
        
        private static class MessengerHandler extends Handler {
    
            @Override
            public void handleMessage(@NonNull Message msg) {
                switch (msg.what) {
                    case 1:
                        //接收到客户端发来的消息
                        Log.d("MessengerService", msg.getData().getString("msg"));
                        //拿到客户端的信使
                        Messenger reply = msg.replyTo;
                        Message replyMsg = Message.obtain(null,2);
                        Bundle bundle = new Bundle();
                        bundle.putString("reply","server receive this message");
                        replyMsg.setData(bundle);
                        try {
                            //给客户端回消息
                            reply.send(replyMsg);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        break;
                    default:
                        super.handleMessage(msg);
                        break;
                }
            }
        }
        //创建一个服务端的信使,同时传入处理消息的handler对象
        private final Messenger messenger = new Messenger(new MessengerHandler());
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            //返回给客户端binder对象
            return messenger.getBinder();
        }
    }
    
    
    1. 在AndroidManifest.xml配置服务,process=":remote"使这个服务处于remote进程。
            ...
            <service
                android:name=".MessengerService"
                android:process=":remote" />
            ...
    
    1. 编写客户端逻辑
    public class MessengerActivity extends AppCompatActivity {
    
        private static class ClientMessengerHandler extends Handler {
    
            @Override
            public void handleMessage(@NonNull Message msg) {
                switch (msg.what) {
                    case 2:
                        //接收到服务端回的消息
                        Log.d("MessengerService", msg.getData().getString("reply"));
    
                        break;
                    default:
                        super.handleMessage(msg);
                        break;
                }
            }
        }
    
        /**
         * 客户端处理消息的信使
         */
        private final Messenger clientMessengerHandler = new Messenger(new ClientMessengerHandler());
    
    
        private Messenger serviceMessenger;
    
        private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //通过IBinder对象,创建出服务端的信使
                serviceMessenger = new Messenger(service);
                Message msg = Message.obtain(null, 1);
                Bundle bundle = new Bundle();
                bundle.putString("msg","hello this is client");
                msg.setData(bundle);
                //通过这种方式,把客户端的信使传递给服务端,用于服务端给客户端回消息
                msg.replyTo = clientMessengerHandler;
                try {
                    //给服务端发送消息
                    serviceMessenger.send(msg);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_messenger);
            Intent it = new Intent(this,MessengerService.class);
            bindService(it,serviceConnection, Context.BIND_AUTO_CREATE);
        }
    }
    

    Messenger工作原理图

    Messenger工作原理图

    总结

    • Messenger对AIDL进行了封装,由于他一次处理一个请求,因此在服务端我们不需要考虑线程同步问题
    • Messenger进行数据传递必须将数据放到Message里面
    • 由于Messenger一次处理一个请求,所有不适用于大量并发的请求
    • Messenger作用主要是为了传递消息,如果我们需求需要调用服务端的具体方法,Messenger无法做到。(需要使用AIDL,自己定义接口来实现此类需求)

    Thanks

    链接: Android开发艺术探索.

    相关文章

      网友评论

        本文标题:Messenger实现进程间通信

        本文链接:https://www.haomeiwen.com/subject/hwavohtx.html