一道腾讯面试官指点:组件之间的跳转和组件通信原理机制
这两者模式更详细的对比,可以查看这篇文章多个维度对比一些有代表性的开源 android 组件化开发方案 #####实现方案事件总线,又可以叫做组件总线,路由+接口,则相对好理解点,今天从阅读它们框架源码,我们来对比这两种实现方案的不同之处。
#####组件总线这边选取的是 ModuleBus 框架,这个方案特别之处在于其借鉴了 EventBus 的思想,组件的注册/注销和组件调用的事件发送都跟 EventBus 类似,能够传递一些基础类型的数据,而并不需要在 Base Moudel 中添加额外的类。所以不会影响 Base 模块的架构,但是无法动态移除信息接收端的代码,而自定义的事件信息类型还是需要添加到 Base Module 中才能让其他功能模块索引。
其中的核心代码是在与 ModuleBus 类,其内部维护了两个 ArrayMap 键对值列表,如下:
private static ArrayMap<Object,ArrayMap<String,MethodInfo>> moduleEventMethods = new ArrayMap<>();
private static ArrayMap<Class<?>,ArrayMap<String,ArrayList<Object>>> moduleMethodClient = new ArrayMap<>();
在使用方法上,在 onCreate()和 onDestroy()中需要注册和解绑,比如
ModuleBus.getInstance().register(this);
ModuleBus.getInstance().unregister(this);
最终使用类似 EventBus 中 post 方法一样,进行两个组件间的通信。这个框架的封装的 post 方法如下
public void post(Class<?> clientClass,String methodName,Object...args){
if(clientClass == null || methodName == null ||methodName.length() == 0) return;ArrayList<Object> clientList = getClient(clientClass,methodName)
for(Object c: clientList){
ArrayMap<String,MethodInfo> methods = moduleEventMethods.get(c);
Method method = methods.get(methodName).m;
method.invoke(c,args);}
可以看到,它是通过遍历之前内部的 ArrayMap,把注册在里面的方法找出,根据传入的参数进行匹配,使用反射调用。#####接口+路由
接口+路由实现方式则相对容易理解点,我之前实践的一个项目就是通过这种方式实现的。具体地址如下:DemoComponent 实现思路是专门抽取一个 LibModule 作为路由服务,每个组件声明自己提供的服务 Service API,这些 Service 都是一些接口,组件负责将这些 Service 实现并注册到一个统一的路由 Router 中去,如果要使用某个组件的功能,只需要向 Router 请求这个 Service 的实现,具体的实现细节我们全然不关心,只要能返回我们需要的结果就可以了。
比如定义两个路由地址,一个登陆组件,一个设置组件,核心代码:
public class RouterPath {public
static final String ROUTER_PATH_TO_LOGIN_SERVICE = "/login/service";public static final String ROUTER_PATH_TO_SETTING_SERVICE = "/setting/service";}
那么就相应着就有两个接口 API,如下:
public interface ILoginProvider extends IProvider {void goToLogin(Activity activity);
}public interface ISettingProvider extends IProvider {
void goToSetting(Activity activity);
}}
这两个接口 API 对应着是向外暴露这两个组件的能提供的通信能力,然后每个组件对接口进行实现,如下:
@Route(path = RouterPath.ROUTER_PATH_TO_LOGIN_SERVICE, name = "登陆页面")
public class LoginService implements ILoginProvider {
@Override
public void init(Context context) {
}@Override
public void goToLogin(Activity activity) {
Intent loginIntent = new Intent(activity, LoginActivity.class);
activity.startActivity(loginIntent);
}
}
这其中使用的到了阿里的 ARouter 页面跳转方式,内部本质也是接口+实现方式进行组件间通信。
调用则很简单了,如下:
ILoginProvider loginService = (ILoginProvider) ARouter.getInstance().build(RouterPath.ROUTER_PATH_TO_LOGIN_SERVICE).navigation();
if(loginService != null){
loginService.goToLogin(MainActivity.this);
}
还有一个组件化框架,就是 ModularizationArchitecture ,它本质实现方式也是接口+实现,但是封装形式稍微不一样点,它是每个功能模块中需要使用注解建立 Action 事件,每个 Action 完成一个事件动作。invoke 只是方法名为反射,并未用到反射,而是使用接口方式调用,参数是通过 HashMap 传递的,无法传递对象。具体详解可以看这篇文章 Android 架构思考(模块化、多进程)。,string>
评论