Android程序员进阶必知架构源码:手把手讲解IPC框架(2)

本文是Android程序员进阶系列的第二篇,深入解析IPC框架的核心思想,包括业务注册、自定义通信协议、binder连接封装和动态代理实现RPC。作者通过实例演示如何解决业务扩展时的文件修改难题,以及简化客户端与服务端通信的过程。
摘要由CSDN通过智能技术生成

作者:享学课堂终身VIP周周
简书ID:波澜步惊
转载请声明出处!

上一期《手把手讲解IPC框架》享学课堂周周同学分享了概念QA以及前置技能、传统方式IPC通信写法与使用IPC框架进行RPC通信的对比以及Demo展示三个部分。这一期他将继续为大家带来手把手讲解IPC框架分享。

正文大纲

一、概念QA以及前置技能
二、传统方式IPC通信写法使用IPC框架进行RPC通信的对比
三、Demo展示
四、框架核心思想讲解
五、写在最后的话
接上一篇:明星学员作品:手把手讲解IPC框架(1)

四、框架核心思想讲解

我们不使用IPC框架时,有两件事非常恶心:

1. 随着业务的扩展,我们需要频繁(因为要新增业务接口)改动 AIDL文件,而且 AIDL修改起来没有任何代码提示,只有到了编译之后,编译器才会告诉我哪里错了,而且 直接引用到的 JavaBean还必须手动再声明一次。实在是不想在这个上面浪费时间。

2. 所有客户端 Activity,只要想进行进程间 binder通信,就不可避免要去手动 bindService,随后去处理 Binder连接,重写 ServiceConnection,还要在适当的时候释放连接,这种业务不相关而且重复性很大的代码,要尽量少写。

IPC框架将会着重解决这两个问题。下面开始讲解核心设计思想

注:1.搭建框架牵涉的知识面会很广,我不能每个细节都讲得很细致,一些基础部分一笔带过的,如有疑问,希望能留言讨论。

2.设计思路都是环环相扣的,阅读时最好是从上往下依次理解.

框架思想四部曲:
1)业务注册

上文说到,直接使用 AIDL通信,当业务扩展时,我们需要对 AIDL文件进行改动,而改起来比较费劲,且容易出错。怎么办?利用 业务注册的方式,将 业务类class对象,保存到服务端 内存中。进入Demo代码 Registry.java

public  class  Ipc {
	/**
* @param business
*/
	public  static  void  register(Class<?> business) {
		//注册是一个单独过程,所以单独提取出来,放在一个类里面去
		Registry.getInstance().register(business);
		//注册机是一个单例,启动服务端,
		// 就会存在一个注册机对象,唯一,不会随着服务的绑定解绑而受影响
	}
	...省略无关代码
}
/**
* 业务注册机
*/
public  class  Registry {
	...省略不关键代码
	/**
* 业务表
*/
	private  ConcurrentHashMap<String, Class<?>> mBusinessMap
	= new  ConcurrentHashMap<>();
	/**
* 业务方法表, 二维map,key为serviceId字符串值,value为 一个方法map  - key,方法名;value
*/
	private  ConcurrentHashMap<String, ConcurrentHashMap<String, Method>> mMethodMap
	= new  ConcurrentHashMap<>();
	/**
* 业务类的实例,要反射执行方法,如果不是静态方法的话,还是需要一个实例的,所以在这里把实例也保存起来
*/
	private  ConcurrentHashMap<String, Object> mObjectMap = new  ConcurrentHashMap<>();
	/**
* 业务注册
* 将业务class的class和method对象都保存起来,以便后面反射执行需要的method
*/
	public  void  register(Class<?> business) {
		//这里有个设计,使用注解,标记所使用的业务类是属于哪一个业务ID,在本类中,ID唯一
		ServiceId serviceId = business.getAnnotation(ServiceId.class);
		//获取那个类头上的注解
		if (serviceId == null) {
			throw  new  RuntimeException("业务类必须使用ServiceId注解");
		}
		String value = serviceId.value();
		mBusinessMap.put(value, business);
		//把业务类的class对象用 value作为key,保存到map中
		//然后要保存这个business类的所有method对象
		ConcurrentHashMap<String, Method> tempMethodMap = mMethodMap.get(value);
		//先看看方法表中是否已经存在整个业务对应的方法表
		if (tempMethodMap == null) {
			tempMethodMap = new  ConcurrentHashMap<>();
			//不存在,则new
			mMethodMap.put(value, tempMethodMap);
			// 并且将它存进去
		}
		for (Method method : business.getMethods()) {
			String methodName = method.getName();
			Class<?>[] parameterTypes = method.getParameterTypes();
			String methodMapKey = getMethodMapKeyWithClzArr(methodName, parameterTypes);
			tempMethodMap.put(methodMapKey, method);
		}
		...省略不关键代码
	}
	...省略不关键代码
	/**
* 如何寻找到一个Method?
* 参照上面的构建过程,
*
* @param serviceId
* @param methodName
* @param paras
* @return
*/
	public  Method findMethod(String serviceId, String methodName, Object[] paras) {
		ConcurrentHashMap<String, Method> map = mMethodMap.get(serviceId);
		String methodMapKey = getMethodMapKeyWithObjArr(methodName, paras);
		//同样的方式,构建一个StringBuilder
		return map.get(methodMapKey);
	}
	/**
* 放入一个实例
*
* @param serviceId
* @param object
*/
	public  void putObject(String serviceId, Object  object) {
		mObjectMap.put(serviceId, object);
	}
	/**
* 取出一个实例
*
* @param serviceId
*/
	public  Object getObject(String serviceId) {
		return mObjectMap.get(serviceId);
	}
}
/**
* 自定义注解,用于注册业务类的
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public  @interface  ServiceId {
	String value();
}

我利用一个单例的 Registry</

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值