写点什么

Android 应用进程间通信之 Messenger 信使使用及源码浅析

发布于: 2021 年 11 月 07 日

Messenger 实现了 IPC 通信,其真实原理也是使用了 AIDL 进行通信,但是和直接使用 AIDL 不同的是 Messenger 利用了 Handler 处理通信,所以它是线程安全的(不支持并发处理);而我们平时用的 AIDL 是非线程安全的(支持并发处理)。所以大多数时候我们应用中是不需要处理夸进程并发处理通信的,所以这时选择 Messenger 会比 AIDL 更加容易操作。



【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流


2 基础实例




分析源码之前我们先来看一个 Demo 例子,其核心逻辑就是客户端进程 client 发送一个消息到服务端进程 remote,服务端进程收到消息后做完处理再回发一个消息到客户端 client,整个过程采用了 Messenger 信使和 Handler 来实现。具体如下:


工程的 Android 管理文件:


<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"


package="com.example.yanbo.myapplication" >


<application


android:allowBackup="true"


android:icon="@mipmap/ic_launcher"


android:label="@string/app_name"


android:theme="@style/AppTheme" >


<activity


android:name=".MainActivity"


android:label="@string/app_name" >


<intent-filter>


<action android:name="android.intent.action.MAIN" />


<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>


</activity>


<!-- ":remote"表示在应用程序里,当需要该 service 时,会自动创建新的进程


"remote"表示创建全局进程,不同的应用程序共享该进程 -->


<service android:name=".RemoteService"


android:process=":remote">


<intent-filter>


<action android:name="com.remote.RemoteService"/>


</intent-filter>


</service>


</application>


</manifest>


工程中的一个独立进程服务端 remote 源码:


/**


  • 另一个进程中的 Service


*/


public class RemoteService extends Service {


public static final int MSG_TAG_REMOTE = 0x110;


public static final int MSG_TAG_CLIENT = 0x111;


private Messenger mRemoteMessenger;


private RemoteHandler mRemoteHandler;


private int mCounter = 0;


@Override


public void onCreate() {


super.onCreate();


mRemoteHandler = new RemoteHandler();


//实例化一个 Messenger 传入当前 Handler


mRemoteMessenger = new Messenger(mRemoteHandler);


}


@Override


public IBinder onBind(Intent intent) {


return (mRemoteMessenger == null) ? null : mRemoteMessenger.getBinder();


}


private class RemoteHandler extends Handler {


@Override


public void handleMessage(Message msg) {


switch (msg.what) {


case MSG_TAG_REMOTE:


//为了把消息回传给 client 端,所以获取 client 端设置的 Messenger


Messenger clientMessenger = msg.replyTo;


if (clientMessenger != null) {


try {


//注意 obtain 第一个参数,前面文章有解释,因为参数 target 不可序列化


clientMessenger.send(Message.obtain(null, MSG_TAG_CLIENT, ++mCounter, 0));


} catch (RemoteException e) {


e.printStackTrace();


}


}


break;


default:


super.handleMessage(msg);


break;


}


}


}


}


工程中的一个独立进程客户端 client 代码:


public class MainActivity extends Activity {


private TextView mTextView;


private Messenger mRemoteMessenger = null;


private Messenger mClientMessenger;


private ClientHandler mClientHandler;


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setContentView(R.layout.activity_main);


mTextView = (TextView) findViewById(R.id.content_show);


//


mClientHandler = new ClientHandler();


mClientMessenger = new Messenger(mClientHandler);


bindService(new Intent(this, RemoteService.class), connection, Context.BIND_AUTO_CREATE);


}


@Override


protected void onDestroy() {


super.onDestroy();


unbindService(connection);


}


private ServiceConnection connection = new ServiceConnection() {


@Override


public void onServiceConnected(ComponentName name, IBinder service) {


mRemoteMessenger = new Messenger(service);


//注意 obtain 第一个参数,前面文章有解释


Message message = Message.obtain(null, RemoteService.MSG_TAG_REMOTE);


message.replyTo = mClientMessenger;


try {


mRemoteMessenger.send(message);


} catch (RemoteException e) {


e.printStackTrace();


}


}


@Override


public void onServiceDisconnected(ComponentName name) {}


};


private class ClientHandler extends Handler {


@Override


public void handleMessage(Message msg) {


switch (msg.what) {


case RemoteService.MSG_TAG_CLIENT:


if (mTextView != null) {


mTextView.setText(msg.arg1+"");


}


break;


default:


super.handleMessage(msg);


break;


}


}


}


}


看着了吧,这就是一个超级简单的 Messenger 使用场景,具体过程比较形象的描述如下图:



相信有了这幅图就不需要再解释啥了吧,这个也够明白了。


【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流


3 Messenger 源码浅析



    《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
    浏览器打开:qq.cn.hn/FTe 免费领取
    复制代码




    通过上面的实例明显可以看出,在不考虑并发的情况下,Messenger 相比 AIDL 无论从代码量、工程结构、复杂度等上都更加胜出一筹。既然这么好用的东东,那就来看看他的源码吧,如下我们先通观一下 Messenger 类的整个核心代码,然后再细说。如下所示:


    /**


    • 关联 Handler 进行跨进程收发消息的信使管理桥梁类

    • 可以看见 Messenger 就是一个信使,就是一个 Object


    */


    public final class Messenger implements Parcelable {


    //其实就是远程的 MessengerService 的 AIDL 接口


    private final IMessenger mTarget;


    //创建一个指向 target Handler 的 Messenger,然后调运 Messenger 的 send 就像 Handler 的 sendMessage


    public Messenger(Handler target) {


    mTarget = target.getIMessenger();


    }


    //跨进程发送消息,通常用 Message.obtain()填充 message 参数,也可以自己 new


    public void send(Message message) throws RemoteException {


    mTarget.send(message);


    }


    //获得 Messenger 的 Binder,一般用在 remote 端获取返回


    public IBinder getBinder() {


    return mTarget.asBinder();


    }


    //如果两个 Messenger 相等则表明指向了相同的 Handler


    public boolean equals(Object otherObj) {


    if (otherObj == null) {


    return false;


    }


    try {


    return mTarget.asBinder().equals(((Messenger)otherObj)


    .mTarget.asBinder());


    } catch (ClassCastException e) {


    }


    return false;


    }


    ......


    //获取 getBinder 相同的 Messenger 对象,一般用在 client 端获取


    public Messenger(IBinder target) {


    mTarget = IMessenger.Stub.asInterface(target);


    }


    }

    评论

    发布
    暂无评论
    Android应用进程间通信之Messenger信使使用及源码浅析