比如定义两个路由地址,一个登陆组件,一个设置组件,核心代码:
public class RouterPath { //注意路由的命名,路径第一个开头需要不一致,保证唯一性 //Login Service public static final String ROUTER_PATH_TO_LOGIN_SERVICE = "/login/service"; //Setting 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<String,String>传递的,无法传递对象。具体详解可以看这篇文章 Android架构思考(模块化、多进程)。
页面跳转页面跳转也算是一种组件间的通信,只不过它相对粒度更细化点,之前我们描述的组件间通信粒度会更抽象点,页面跳转则是定位到某个组件的某个页面,可能是某个Activity,或者某个Fragment,要跳转到另外一个组件的Activity或Fragment,是这两者之间的通信。甚至在一般没有进行组件化架构的工程项目中,往往也会封装页面之间的跳转代码类,往往也会有路由中心的概念。不过一般 UI 跳转基本都会单独处理,一般通过短链的方式来跳转到具体的 Activity。每个组件可以注册自己所能处理的短链的 Scheme 和 Host,并定义传输数据的格式,然后注册到统一的 UIRouter 中,UIRouter 通过 Scheme 和 Host 的匹配关系负责分发路由。但目前比较主流的做法是通过在每个 Activity 上添加注解,然后通过 APT 形成具体的逻辑代码。
下面简单介绍目前比较主流的两个框架核心实现思路:
ARouterARouter 核心实现思路是,我们在代码里加入的@Route注解,会在编译时期通过apt生成一些存储path和activityClass映射关系的类文件,然后app进程启动的时候会拿到这些类文件,把保存这些映射关系的数据读到内存里(保存在map里),然后在进行路由跳转的时候,通过build()方法传入要到达页面的路由地址,ARouter会通过它自己存储的路由表找到路由地址对应的Activity.class(activity.class = map.get(path)),然后new Intent(),当调用ARouter的withString()方法它的内部会调用intent.putExtra(String name, String value),调用navigation()方法,它的内部会调用startActivity(intent)进行跳转,这样便可以实现两个相互没有依赖的module顺利的启动对方的Activity了。
ActivityRouterActivityRouter 核心实现思路是,它是通过路由 + 静态方法来实现,在静态方法上加注解来暴露服务,但不支持返回值,且参数固定位(context, bundle),基于apt技术,通过注解方式来实现URL打开Activity功能,并支持在WebView和外部浏览器使用,支持多级Activity跳转,支持Bundle、Uri参数注入并转换参数类型。它实现相对简单点,也是比较早期比较流行的做法,不过学习它也是很有参考意义的。
小结总的来说,组件间的通信机制在组件化编程和组件化架构中是很重要的一个环节,可能在每个组件独自开发阶段,不需要与其他组件进行通信,只需要在内部通信即可,当处于组件集成阶段,那就需要大量组件进行互相通信,体现在每个业务互相协作,如果组件间设计的不好,打开一个页面或调用一个方法,想当耗时或响应慢,那么体现的则是这个APP使用比较卡顿,仅仅打开一个页面就是需要好几秒才能打开,则严重影响使用者的体验了,甚至一些大型APP,可能组件分化更小,种类更多,那么组件间的通信则至关重要了。所以,要打造一个良好的组件化框架,如何设计一个更适合自己本身的业务类型的通信机制,就需要多多进行思考了。
参考文章:
1,https://github.com/luckybilly/AndroidComponentizeLibs