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

概述

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

YKProBus

怎么使用?

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 classMainActivityextendsActivityimplementsIMessageHandler{
  ...
    
   
    /**
     * 接收其它进程发送过来的消息
     *
     * @return
     */@Override
    public Handler getHandler() {
        returnnewHandler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case0x001:
                       ...
                        break;
                }
            }
        };
    } 
  ...
}

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

 EventManager.getInstance().registerMessager(int messageTag, Object obj);

框架设计大概流程

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 = newMessengerImpl();
            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 文件。

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

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

客服端

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

IMessenger mServiceMessenger = IMessenger.Stub.asInterface(service);

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

    /**
     * 服务端消息是否连接成功
     */privateclassEventServiceConnectionimplementsServiceConnection {
        @OverridepublicvoidonServiceConnected(ComponentName name, IBinder service) {
            isBindApplication = true;
            // 得到服务信使对象
            mServiceMessenger = newMessenger(service);

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

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

        }

        @OverridepublicvoidonServiceDisconnected(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 源码。

系列文章

移动架构 (一) 详解架构设计中UML图的使用

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

移动架构 (三) AMS 源码分析

移动架构 (四) EventBus源码分析及实现自己的轻量级 EventBus 框架

移动架构 (五) 了解Android数据持久化

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

移动架构 (七) 组件化架构设计思想

移动架构 (八) 动态化加载插件技术模型实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金戈鐡馬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值