改造Arouter的模块调用,创建更适用于组件化开发的路由框架

作者catRuan ,转载请注明出处

      Arouter是阿里开发的一款用于模块间跳转、通讯的路由工具 Arouter源码

      关于Arouter的实现原理,请参照作者另外一篇博客 Arouter源码解读

      公司在进行组件化开发时有幸选用了Arouter作为模块管理工具,在使用过程中发现其并非能够彻底解决跨模块调用时的耦合的问题

     例如,当我想在当前模块中调用其他模块的方法时,Arouter是这么做的:

  方式一

((HelloService) ARouter.getInstance().build("/service/hello").navigation()).sayHello("mike");

 这种调用方式需要在调用的模块里将Arouter返回的对象强转为目标模块,这对于组件化开发来说简直是一个噩梦 ,我们希望组件化开发过程中每一个模块是相互独立且互不依赖的,严格来说,做到互不依赖是不可能的,所以大部分组件化框架的理念里都有一个base模块,每个功能模块都引用这个base模块,且通过base模块调用其他模块,但Arouter提供的这种模块间通许方式使我们不得不在调用模块中强耦合被调用模块。

    因此,Arouter提供了第二种调用方式

   方式二

ARouter.getInstance().navigation(HelloService.class).sayHello("mike");

这种调用方式相较于第一种方式要好很多,通过类名来调用模块中的方法,注意,这里的类一定是一个接口(请参考Arouter的源码讲解),对于组件化结构的项目来说,这个接口可以写在具体的某个模块里,那么当我要调用这个接口的实现类时,就必须强耦合这个模块。所以,我们可以将接口写在base模块里,这听起来很棒,因为我们终于做到不引用具体模块而调用他的方法了。乍看之下,这种调用方式看似完美无缺,但是想想模块中每一个想要暴露出去让其他模块调用的方法都要在base模块中映射成接口,那也是一项相当烦躁的工作

     在考虑到如上问题带来的不便,我对Arouter进行了改造,保留了其原有的所有Api,而添加跨模块调用的新方式:仅仅通过route调用方法,即调用模块仅需要知道被调用模块的方法名和参数列表,并不需要主动获取被调模块的实例。

       具体用法如下

      1.跨模块调用同步方法,对比Arouter原有调用方式,不需要创建模块实例,即模块间没有强耦合

 // 同步方法调用(无参数/无返回)
  ARouter.getInstance().build("/module/service").call("test1");
  
  // 同步方法调用(带参数/无返回)
  ARouter.getInstance().build("/module/service").call("test2", 111, "小阮");
  
  // 同步方法调用(带参数/有返回)
  Object result = ARouter.getInstance().build("/module/service").call("test3", 1111, "小阮", new TestBean(-111, "down"));
  Log.i("ruan", "调用test3,返回值:" + result);
  
  // 同步方法调用(无参数/有返回)
  Object result2 = ARouter.getInstance().build("/module/service").call("test4");
  Log.i("ruan", "调用test4,返回值:" + result2.toString());

      2. 跨模块调用异步方法,根据route调用,不需要引入模块

// 同步方法调用(无参数/有返回),对比Arouter原有调用方式,不需要创建模块实例,即模块间没有强耦合
ARouter.getInstance()
         .build("/module/service")
         .call("test5", "参数1", new MethodCallback<TestBean>() {

             @Override
             public void onNext(Object... object) {

             }

             @Override
             public void onError(String errorMsg) {

             }

             @Override
             public void onComplete(TestBean result) {
                 Log.i("ruan", "调用test5,返回值:" + result.toString());
             }

      3. 暴露模块方法(只允许在Activity或Iprovider中暴露)

Route(path = "/module/service")
public class TestService implements IProvider {

    @Override
    public void init(Context context) {

    }

    @Method
    public void test1() {
        Log.i("ruan", "test1");
    }

    @Method
    public void test2(int parma1, String param2) {
        Log.i("ruan", "test2-" + parma1 + "," + param2);
    }

    @Method
    public int test3(int parma1, String param2, TestBean testBean) {
        Log.i("ruan", "test3-" + parma1 + "," + param2 + "," + testBean);
        return 1;
    }

    @Method
    public TestBean test4() {
        Log.i("ruan", "test4");
        return new TestBean(1, "hahah");
    }

    @Method
    public void test5(String params1, @MethodCallBack MethodCallback<TestBean> callback) {
        Log.i("ruan", "test4");
        TestBean result = new TestBean(1, "result");
        callback.onComplete(result);
    }
}
目前已经的缺陷
1、暂时只支持在本类中暴露方法,即子类不会继承父类暴露的方法

 本库已开源:https://github.com/CatRuan/ARouter    

猜你喜欢

转载自blog.csdn.net/u011791526/article/details/82994750