注册

移动架构 (六) 轻量级进程间通信框架设计

移动架构 (一) 架构第一步,学会画各种 UML 图

移动架构 (二) Android 中 Handler 架构分析,并实现自己简易版本 Handler 框架

动架构 (三) AMS 源码分析

移动架构 (四) EventBus 3.1.1 源码分析及实现自己的轻量级 EventBus 框架,根据 TAG 发送接收事件。

移动架构 (五) 仅仅对 Java Bean 的操作,就能完成对数据持久化

概述


现在多进程传递数据使用越来越广泛了,在 Android 中进程间通信提供了 文件AIDLBinderMessengerContentProviderSocketMemoryFile 等,实际开发中使用最多的应该是 AIDL ,但是 AIDL 需要编写 aidl 文件,如果使用 AIDL 仅仅是为了传递数据, 那么 YKProBus 是你不错的选择。


YKProBus


怎么使用?


16c801f1cbb8119e?imageslim


1. root/build.gradle 中添加框架 maven


	allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
复制代码

2. app/build.gradle 中添加框架 依赖


	dependencies {
implementation 'com.github.yangkun19921001:YKProBus:1.0.1'
}
复制代码

3. 发送进程绑定接收进程服务


EventManager.getInstance().bindApplication(Context context,String proName);
复制代码

4. 发送消息


 EventManager.getInstance().sendMessage(int messageTag,Bundle bundle);
复制代码

5. 接收进程中需要在清单文件注册服务


<service       
android:name="com.devyk.component_eventbus.proevent.service.MessengerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.devyk.component_eventbus.service"></action>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
复制代码

6. 接收消息


6.1 在需要接收消息的类中实现 IMessageHandler 并实例化一个 Handler 用于接收发送进程发来的消息


public class MainActivity extends Activity implements IMessageHandler{
...


/**
* 接收其它进程发送过来的消息
*
* @return
*/
@Override
public Handler getHandler() {
return new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0x001:
...
break;
}
}
};
}
...
}
复制代码

6.2 注册当前类需要接收消息


 EventManager.getInstance().registerMessager(int messageTag, Object obj);
复制代码

框架设计大概流程


Messenger-YKProBus-.png


Messenger 源码分析


Messenger 内部其实也是依赖 aidl 实现的进程间通信。


服务端


    @Override
public IBinder onBind(Intent intent) {
return mServiceMessenger.getServiceMessenger().getBinder();
}
复制代码

getBinder() 跟进去


    public IBinder getBinder() {
return mTarget.asBinder();
}
复制代码

mTarget 从何而来,从源码找找


    public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
复制代码

这里是我们实例化 服务端 Messenger 传入的 Handler target


    /**
* 初始化服务端 Messenger
*/
public MessengerManager() {
if (null == mServiceMessenger)
mServiceMessenger = new Messenger(mMessengerServiceHandler);
}
复制代码

那么我们在点击 getIMessenger() 在看看内部实现


    final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}

复制代码

继续点击 MessengerImple


    private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
复制代码

这个是一个内部实现的类,可以看到继承的是 IMessenger.Stub 然后实现 send (Message msg) 函数,然后通过 mTarget.sendMessage(msg) 发送消息,最后在我们传入进去的 mMessengerServiceHandler 的 handleMessage (Message) 接收发来的消息。


既然这里内部帮我们写了 aidl 文件 ,并且也继承了 IMessenger.Stub 我们今天就要看到 aidl 才死心 , 好吧我们来找找 IMessenger aidl 文件。


IMessenger-aidl-.jpg


可以看到是在 framework/base/core/java/android/os 路径中,我们点击在来看下文件中怎么写的


IMessenger-aidl-2.jpg


内部就一个 send 函数,看到这,大家应该都明白了,Messenger 其实也没什么大不了,就是系统内部帮我们写了 aidl 并且也实现了 aidl ,最后又帮我们做了一个 Handler 线程间通信,所以服务端收到了客服端发来的消息。


客服端


客服端需要在 bindServicer onServiceConnected 回调中拿到 servicer, 平时我们自己写 应该是这么拿到 Ibinder 对象吧


IMessenger mServiceMessenger = IMessenger.Stub.asInterface(service);
复制代码

但是我们实际客服端是这样拿到服务端的 Messenger


    /**
* 服务端消息是否连接成功
*/
private class EventServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
isBindApplication = true;
// 得到服务信使对象
mServiceMessenger = new Messenger(service);

//将本地信使告诉服务端
registerMessenger();

String proName = ProcessUtils.getProName(mApplicationContext);
Log.d(TAG, " EventServiceConnection " + proName);

}

@Override
public void onServiceDisconnected(ComponentName name) {
isBindApplication = false;
}
}
复制代码
// 得到服务信使对象
mServiceMessenger = new Messenger(service);
复制代码

跟进去


public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
复制代码

这不就是我们刚刚说的自己实现的那种写法吧,到这里我们都懂了吧,我们平时写的 aidl android 中已经帮我们写了,想当于在 aidl 中封装下就变成了现在的 Messenger , 而我们又在 Messenger 上封装了下,想当于 三次封装了,为了使用更简单。封装才是王道!


总结


我们自己的 YKProBus 为了进程间通信使用更简单方便,其实相当于在 AIDL 中的三次封装。想要了解的可以去看下我具体的封装或者 Messenger 源码。


感谢大家抽空阅览文章,谢谢!


作者:DevYK
链接:https://juejin.cn/post/6844903910587498510
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册