Hermes是Android中的跨进程通信框架,由饿了么出品。主要使用Binder来实现的跨进程通信。跨进程通信在Android中很重要,但是实现起来可以说稍微有些麻烦,尤其在两个进程通信的数据类型很多时,要写的中间文件或者AIDL文件就很多。而Hermes很好的解决了这个问题,完全不用你去写Binder文件或者AIDL文件。由于Hermes是在16年开发的,之后一直没有维护,所以直接使用会报错。估计这也是Hermes一直没有火起来的原因吧,毕竟跨进程通信不了解的同学来说,使用的时候报错就直接抛弃了。报错的问题很好解决,我们进入正题来说。
目录
一、解决Hermes使用时报错的问题
解决这个错误很简单,我们先把源码下载下来,修改错误,重新打一个包,放在自己的项目中使用就可以了。因为Hermes中的代码还在依赖v7和v4的包,而我司的项目早就适配AndroidX了,所以我直接把Hermes的源码拷贝在新module里,然后打包依赖。
报错主要是因为源码中TypeUtils这个类,我们把这句话注释掉就可以了
二、Hermes使用
我这里以单例为例子来说(假设B进程想要获取A进程中某单例的属性值)
首先在清单文件中注册服务
<service android:name=".HermesService$HermesService0"/>
创建接口ISingleton和单例类Singleton和
@ClassId("Singleton")
public interface ISingleton {
@MethodId("setValue")
void setValue(String value);
@MethodId("getValue")
String getValue();
}
@ClassId("Singleton")
public class Singleton {
private static Singleton sInstance;
private String value;
private Singleton(){}
public static Singleton getInstance(){
if(sInstance==null){
synchronized (Singleton.class){
if(sInstance==null){
sInstance = new Singleton();
}
}
}
return sInstance;
}
@MethodId("setValue")
public void setValue(String value) {
this.value = value;
}
@MethodId("getValue")
public String getValue() {
return value;
}
}
有一点需要说明:ISingleton和Singleton两个类不一定要有继承关系,当然如果是继承关系的话也不会出错。但是在两个类中ClassId和MethodId要相同
我们从这两个中找到了两个新的东西ClassId和MethodId。顾名思义,ClassId其实就是Hermes来标识此类的一个标记,MethodId是用来标识方法的。这两个类中,ClassId的值相同,对应方法的MethodId相同。
创建MainActivity(主进程,相当于进程A),对单例类进行注册
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册
Hermes.register(Singleton.class);
//给单例的属性值赋值
Singleton.getInstance().setValue("gzc");
}
/**
* 跳转到SecondActivity(子进程,相当于进程B)
* @param view
*/
public void jumpToSecond(View view) {
startActivity(new Intent(this,SecondActivity.class));
}
}
一定不要忘了注册这一步,只要某个类想在两个进程中通信,就必须要注册
创建SecondActivity(子进程,相当于进程B)
public class SecondActivity extends AppCompatActivity {
ISingleton singleton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//连接成功的监听
Hermes.setHermesListener(new HermesListener() {
@Override
public void onHermesConnected(Class<? extends HermesService> service) {
Log.d("SecondActivity","链接成功");
singleton = Hermes.getInstance(ISingleton.class);
Log.d("SecondActivity","value:"+singleton.getValue());
}
});
//连接
Hermes.connect(getApplicationContext());
}
@Override
protected void onDestroy() {
super.onDestroy();
Hermes.disconnect(getApplicationContext());
}
}
首先,先进行连接操作,成功后Hermes调用getInstance方法,参数为ISingleton.class。此时返回的为ISingleton对象,这时候调用getValue方法,获取的就是主进程Singleton类中value值。最后不要忘了disconnect。
Hermes除了getInstance方法外,还有newInstance和getUtilityClass。newInstance的通信类型为普通类;getUtilityClass的通信类型为普通类中的静态方法。在我看来,这两种平时可能应用的少一点,如果使用newInstance创建的话,相当于在A进程中创建了对象,和直接在B进程中创建没什么区别吧;而使用getUtilityClass,并不会在A进程中创建对象,我们可以在源码中可以看到,invokeMethod方法都是空的,关键是调用方法,获取A进程中静态方法的值。
三、Hermes原理分析
如果大家想看Hermes源码的话,建议先学习Binder相关的只是,知道怎么使用Binder进行跨进程通信。
虽然Hermes的源码看着不少,但是顺着使用的代码来捋顺的话,还是不难的。从源码上来看,B进程(子进程或其他进程)并没有做特殊的工作,它的工作只有两个:发送具体的指令和接收A进程(主进程或自己App的进程)的通信数据。我们画一张流程图来了解一下(以getInstance为例,假设ClassId和MethodId已经按上面的介绍添加完成):
Hermes的确不难,静下心来仔细阅读源码都会明白其中的道理的。如果有什么问题欢迎在留言区留言,我每天都会看的,哈哈