1. 程式人生 > >改造Arouter的模組呼叫,建立更適用於元件化開發的路由框架

改造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、暫時只支援在本類中暴露方法,即子類不會繼承父類暴露的方法