网站 源码 php,导航网站 php,网站建设管理ppt,能不能模仿百度一样做搜索引擎网站一. 概述 Android中比较有代表性的两大通信机制#xff1a;1. 线程间Handler通信 2. 进程间Binder通信#xff0c;本篇文章中我们在理解AIDL原理的基础上来解读一下Messenger的源代码#xff0c; 并结合示例Demo加深理解。 在看本篇文章前#xff0c;建议先查阅一下笔者的…一. 概述 Android中比较有代表性的两大通信机制1. 线程间Handler通信 2. 进程间Binder通信本篇文章中我们在理解AIDL原理的基础上来解读一下Messenger的源代码 并结合示例Demo加深理解。 在看本篇文章前建议先查阅一下笔者的 Android 进程间通信机制(六) 手写AIDL文件 首先说下我对Messenger的个人理解
1. 从概念上阐述 Messenger进程间通信的信使是一个轻量级的IPC通信方案 和Message消息不是一个概念。 2. 从实现上描述 实现 AIDL Handler 它的底层实现原理还是使用 AIDL, 对应的文件为(IMessenger.aidl)
相应的接口方法
oneway interface IMessenger {void send(in Message msg);
}
Messenger使用了Handler进行通信 调用的这句代码 private final class MessengerImpl extends IMessenger.Stub {public void send(Message msg) {msg.sendingUid Binder.getCallingUid();//核心代码Handler.this.sendMessage(msg);}} 3. 使用场景 两个进程间只进行简单的轻量级通信 不需要处理多线程的业务场景。 二. 示例
2.1 先看一下清单文件
?xml version1.0 encodingutf-8?
manifest xmlns:androidhttp://schemas.android.com/apk/res/androidpackagecom.example.messengertestapplicationandroid:allowBackuptrueandroid:iconmipmap/ic_launcherandroid:labelstring/app_nameandroid:roundIconmipmap/ic_launcher_roundandroid:supportsRtltrueandroid:themestyle/Theme.MessengerTestactivityandroid:name.MainActivityandroid:exportedtrueandroid:process:clientintent-filteraction android:nameandroid.intent.action.MAIN/category android:nameandroid.intent.category.LAUNCHER//intent-filter/activityserviceandroid:name.MyServiceandroid:exportedtrueandroid:enabledtrueandroid:process:server/service/application/manifest
我把MainActivity作为客户端 MyService作为服务端 用android:process标记让两个组件运行在不同的进程中。
2.2 客户端
public class MainActivity extends AppCompatActivity {private static final String TAG MainActivity;private Messenger mServiceMessenger;//创建客户端 Messenger 对象并绑定 Handlerprivate Messenger mClientMessenger new Messenger(new MessengerHandler());private static final class MessengerHandler extends Handler {Overridepublic void handleMessage(NonNull Message msg) {super.handleMessage(msg);switch (msg.what) {case MyConstants.MSG_FROM_SERVER: //接受来自 服务端 的消息Log.d(TAG, receive msg from server: msg.getData().get(reply));break;default:break;}}}Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//绑定服务端的 Service, 成功后用返回的 IBinder 对象创建 MessengerIntent intent new Intent(this, MyService.class);bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}private ServiceConnection mConnection new ServiceConnection() {Overridepublic void onServiceConnected(ComponentName name, IBinder binder) {mServiceMessenger new Messenger(binder); // 获取服务端的 Messenger对象, 通过它向服务端发送消息Message msg Message.obtain(null, MyConstants.MSG_FROM_CLIENT);Bundle data new Bundle();data.putString(msg, hello, this is client);msg.setData(data);msg.replyTo mClientMessenger ; //将客户端的 Messenger 传给 服务端try {mServiceMessenger.send(msg);} catch (RemoteException e) {e.printStackTrace();}}Overridepublic void onServiceDisconnected(ComponentName name) {}};
} 2.3 服务端
public class MyService extends Service {private static final String TAG MyService;//服务端创建 Messenger对象并绑定对应 Handler, 用于处理 Client 发过来的消息private final Messenger mServiceMessenger new Messenger(new MessengerHandler());NullableOverridepublic IBinder onBind(Intent intent) {//返回 Binder 对象给 Clientreturn mServiceMessenger.getBinder();}public MyService() {}private static class MessengerHandler extends Handler {Overridepublic void handleMessage(NonNull Message msg) {super.handleMessage(msg);switch (msg.what) {case MyConstants.MSG_FROM_CLIENT:Log.d(TAG, receive msg from client: msg.getData().getString(msg));Messenger clientMessenger msg.replyTo; //获取传递过来的客户端Messenger对象Message replyMsg Message.obtain(null, MyConstants.MSG_FROM_SERVER);Bundle bundle new Bundle();bundle.putString(reply, server have receive your msg);replyMsg.setData(bundle);try {clientMessenger.send(replyMsg);} catch (RemoteException e) {e.printStackTrace();}break;default:break;}}}
}2.4 消息常量
public class MyConstants {public static final int MSG_FROM_SERVER 2;public static final int MSG_FROM_CLIENT 1;
} 2.5 运行结果
16:12:57.139 31928 31928 D MyService: receive msg from client:hello, this is client
16:12:57.181 31894 31894 D MainActivity: receive msg from server: server have receive your msg
客户端和服务端关键代码处有注释说明方便理解。 三. 模型
上面Demo可以用如下图来说明 四. 源码解析
大多数应用,跨进程只是一对一通信, 并且无需执行多线程处理的业务, 此时使用Messenger更适合一点。
我们重点看如下5个方法
public final class Messenger implements Parcelable {......//1. mTarget 为 IMessenger接口实例化对象private final IMessenger mTarget;//2. 创建一个指向target Handler的Messenger// 然后调运Messenger的send 实质是调用Handler的sendMessage方法public Messenger(Handler target) {mTarget target.getIMessenger();}//3. 跨进程发送消息方法public void send(Message message) throws RemoteException {mTarget.send(message);}//4. 获得Messenger的Binder一般用在service端获取返回public IBinder getBinder() {return mTarget.asBinder();}//5. 获取getBinder相同的Messenger对象一般用在client端获取public Messenger(IBinder target) {mTarget IMessenger.Stub.asInterface(target);}......}
第1个方法 mTarget 为 IMessenger 接口实例化对象 在java语法规则中接口类不能直接创建对象 只能实例化实现该接口的类对象我们来看看IMessenger.java 它是IMessenger.aidl 文件通过aapt编译自动生成的具体输出路径为
out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/android/os/IMessenger.java
public interface IMessenger extends android.os.IInterface {......
}
它是一个public 接口类不能直接通过new IMessenge() 来创建对象但是可以new 实现了该接口的类对象。 第2和5个方法 是Messenger类的两个构造方法 private final IMessenger mTarget;public Messenger(Handler target) {mTarget target.getIMessenger();}public Messenger(IBinder target) {mTarget IMessenger.Stub.asInterface(target);}
可以这样子理解两个方法的用途
1. 参数为Handler的是远程端进程的实例方法
2. 参数为IBinder的是客户端进程的实例方法
第1个构造方法的内容
//frameworks/base/core/java/android/os/Handler.java 文件中IMessenger mMessenger;//对于一个Handler对象来说getIMessenger得到的Messenger是一个单例模式对象
final IMessenger getIMessenger() {synchronized (mQueue) {if (mMessenger ! null) {return mMessenger;}//这里就是new了一个实现该接口类的对象mMessenger new MessengerImpl();return mMessenger;}}//这里其实是IMessenger.aidl的接口send的具体实现类private final class MessengerImpl extends IMessenger.Stub {public void send(Message msg) {msg.sendingUid Binder.getCallingUid();//核心还是与该进程绑定的Handler去发送消息Handler.this.sendMessage(msg);}}
结论Messenger类中的mTarget其实就是一个Handler中 实现了IMessenger远程IPC send接口的MessengerImpl 单例对象。 第2个方法的使用就是在客户端拿到服务端的Messenger对象
在MyService.java中 我们看下Service中的onBind实现其调运了Messenger的getBinder方法这个方法源码如下 //服务端创建 Messenger对象并绑定对应 Handler, 用于处理 Client 发过来的消息private final Messenger mServiceMessenger new Messenger(new MessengerHandler());NullableOverridepublic IBinder onBind(Intent intent) {//返回 Binder 对象给 Clientreturn mServiceMessenger .getBinder();} public IBinder getBinder() {return mTarget.asBinder();}//调用mTarget.asBinder()方法也即是this对象自己//在 Stub类中public static abstract class Stub extends android.os.Binder implements android.os.IMessenger{....Override public android.os.IBinder asBinder(){return this;}....}//还记得上面的Handler类中的 MessengerImpl 实现了 IMessenger.StubIMessenger mMessenger new MessengerImpl()private final class MessengerImpl extends IMessenger.Stub {}
可以看见其实asBinder返回的就是this 也就是把Service中的Messenger通过onBind方法返回给客户端。
然后再回到客户端 MainActivity.java 中的 onServiceConnected 方法 private Messenger mServiceMessenger;private final IMessenger mTarget;// 1. 获取服务端的 Messenger对象, 通过它向服务端发送消息public void onServiceConnected(ComponentName name, IBinder binder) {mServiceMessenger new Messenger(binder); // 2. 上面的 new Messenger(binder)调用方法/*** 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);}通过asInterface方法转化一下由于不在同一个进程会把Stub转换成Proxy代理对象 public static android.os.IMessenger asInterface(android.os.IBinder obj){if ((objnull)) {return null;}android.os.IInterface iin obj.queryLocalInterface(DESCRIPTOR);if (((iin!null)(iin instanceof android.os.IMessenger))) {return ((android.os.IMessenger)iin);}return new android.os.IMessenger.Stub.Proxy(obj);}
就这样客户端就拿到了服务端的Messenger对象接下来就可以在客户端中用Messenger给服务端发送消息了。 五. 小结
1. 客户端和服务端都有自己的Handler对象用于在各自的进程中接收处理消息发送消息则是和Handler绑定的Messenger对象。
2. 通过IMessenger.aidl 中的 send(Message msg)方法进行跨进程通信 注意 msg.replyTo变量实则是一个Messenger对象 用于两个进程传递各自的Messenger对象。