Android进程通讯方式有很多,如Socket、ContentProvider、共享文件(这种方式的缺点是不支持并发写,同时需要手动操作IO)、AIDL、Messenger(底层实现也是AIDL)等。关于AIDL和Messenger的使用详见Android知识点总结(四)进程间通信。
Android中IPC方式的使用不是有诸多限制,就是使用起来比较麻烦,所以搭建一套简单易用的IPC框架是很有必要的。
RPC:从客户端上通过参数传递的方式调用一个远程函数并得到返回的结果,隐藏底层的通讯细节。在使用形式上就像调用本地函数一样去直接调用远程函数
场景
在服务进程中开启定位服务(demo里对应GpsService),在App主进程或者其他APP中获得定位结果(demo对应MainAcivity)。
框架使用预览
1. 编写业务接口及接口实现
ILocationManager
@ServiceId("LocationManager")
public interface ILocationManager {
Location getLocation();
}
LocationManager
@ServiceId("LocationManager")
public class LocationManager {
private static final LocationManager OUR_INSTANCE = new LocationManager();
public static LocationManager getDefault() {
return OUR_INSTANCE;
}
private LocationManager(){}
private Location location;
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
}
二者通过自定义注解的方式相关联,RPC框架主要就是通过反射业务接口的实现类LocationManager来完成通信。
2. 服务进程使用方法
将业务接口实现类注册到RPC框架即可,RPC框架内部通过反射的方式拿到LocationManager的相关信息,通过AILD将数据传递到主进程。
/**
* 服务进程
*/
public class GpsService extends Service {
public GpsService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
//模拟定位
LocationManager.getDefault().setLocation(new Location("岳麓区天之道", 1.1d, 2.2d));
//将LocationManager注册到框架
IPC.regist(LocationManager.class);
}
}
3. 主进程使用方法
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//开启服务进程
startService(new Intent(this, GpsService.class));
//通过RPC框架连接服务 IPCService服务是框架内部的公共服务,IPCService0是内部服务的子类
//和服务进程设置为同一进程
IPC.connect(this, IPCService.IPCService0.class);
}
public void showLocation(View view) {
//主进程利用框架获取业务实现类的代理对象,然后用代理对象直接调用接口方法
//使用形式上就像调用本地函数一样去直接调用远程函数
ILocationManager location = IPC.getInstanceWithName(IPCService.IPCService0.class, ILocationManager.class, "getDefault");
Toast.makeText(this, "当前位置:" + location.getLocation(), Toast.LENGTH_LONG).show();
}
}
以上就是整个框架的应用示例
RPC框架实现原理
接下来就从零开始手写整个RPC框架
1、业务注册
public class IPC {
//服务端
//==================================================================
//注册
public static void regist(Class<?> service) {
Registry.getInstance().regist(service);
}
...
}
IPC.java只是对外的一个窗口,真正的注册实现在Registry
public class Registry {
private static volatile Registry instance;
/**
* 服务表 记录业务接口实现类的Class对象 对应本例即LocationManager
*/
private ConcurrentHashMap<String, Class<?>> mServices = new ConcurrentHashMap<>();
/**
* 方法表 记录业务接口实现类的相关方法
*/
private ConcurrentHashMap<Class<?>, Map<String, Method>> mMethods = new ConcurrentHashMap<>();
/**
* 业务实现类的实例,要反射执行非静态方法,是需要一个实例对象的,所以把实例保存起来
*/
private Map<String, Object> mObjects = new HashMap<>();
private Re