天天看点

[Android IPC] 一.Messenger一.Messenger有什么用二.Messenger怎么用二.Messenger原理

Android最常用来快进程通讯的手段是AIDL,这个大家都很熟悉了。今天我们来介绍另一个比AIDL使用起来更简单的跨进程方式Messenger,其实Messenger的内部实现就是用的AIDL,那么为什么我还要介绍他呢?主要是为了后面要介绍的AsyncChannel打个基础,好了,快点进入正题吧!

一.Messenger有什么用

Messenger就是用来发送消息的,核心方法只有一个send。从这个方法来看,显然Messenger是单向的,那如果要双向通信怎么办。其实很简单,两边分别创建一个Messenger对象,然后把创建的Messenger对象发给对方,这样就可以相互send消息了。

二.Messenger怎么用

假设张三和李四要用Messenger进行通信

张三首先这么操作:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

		// 1.张三创建Messenger对象
        MessengerHandler messengerHandler = new MessengerHandler();
        Messenger messenger = new Messenger(messengerHandler);

        // 2.将Messenger对象通过Intent传递给李四
        Intent intent = new Intent();
        intent.setClassName("com.frezrik.lisi", "com.frezrik.lisi.MainActivity");
        intent.putExtra("MESSENGER", messenger);
        startActivity(intent);

    }

    public static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            // 3.等待李四发送过来的消息
            Log.w("zmzm", "zhangsan recv:" +  msg.getData().getString("MSG"));

            // 4.收到李四的消息后,张三回复消息
            Bundle bundle = new Bundle();
            bundle.putString("MSG", "zhangsan say hello");

            Message message = Message.obtain();
            message.setData(bundle);
            try {
                Log.w("zmzm", "zhangsan send hello");
                msg.replyTo.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

}
           

李四的操作:

public class MainActivity extends AppCompatActivity {

    private boolean mBound;	
	private Messenger mZsMessenger;
    private Messenger mMessenger;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

		// 1.李四拿到张三传过来的Messenger
        Intent intent = getIntent();
        mZsMessenger = intent.getParcelableExtra("MESSENGER");
        if (mZsMessenger != null) {
            mBound = true;
        }

		// 2.李四也创建一个Messenger,等下给张三来回复消息
		MessengerHandler messengerHandler = new MessengerHandler();
        mMessenger = new Messenger(messengerHandler);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBound = false;
    }

    public void click(View view) {
        if (mBound) {
			// 3.李四发送消息给张三
            try {
                Bundle bundle = new Bundle();
                bundle.putString("MSG", "lisi say hello");

                Message message = Message.obtain();
                message.replyTo = mMessenger; // 把李四创建的Messenger打包起来,等下一起发给张三
                message.setData(bundle);

                Log.d("zmzm", "lisi send hello");
                mZsMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

    }

    public static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            // 4.收到了张三回复的消息
            Log.d("zmzm", "lisi recv:" +  msg.getData().getString("MSG"));
        }
    }
}
           

二.Messenger原理

相关源码路径:

frameworks/base/core/java/android/os/IMessenger.aidl

frameworks/base/core/java/android/os/Messenger.java

frameworks/base/core/java/android/os/Handler.java

张三创建Messenger时,张三就是Messenger的服务端

//Messenger.java

    private final IMessenger mTarget;
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
           
//Handler.java

    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);
        }
    }
           

看到这里就很清晰了,张三作为服务端实现了IMessenger.aidl的send方法

李四调用send方法

public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }
           

这不就是AIDL调用吗,李四作为客户端拿到服务端对象mTarget,aidl调用send方法。Message的内容就被传到了服务端,实现了跨进程调用。后面的流程就都是在张三的进程里进行的了,Handler.this.sendMessage(msg)就是我们熟悉的handler了,msg通过enqueueMessage方法插入消息队列,Looper.loop()方法里dispatchMessage,最后通过handleMessage将消息送达