Android完全組件化—如何使用Arouter

獲得Android組件化方案已經開源,參見Android組件化方案開源。方案的解讀文章是一個小的系列,這是系列的第五篇文章:java

  1. Android完全組件化方案實踐
  2. Android完全組件化demo發佈
  3. Android完全組件化-代碼和資源隔離
  4. Android完全組件化—UI跳轉升級改造
  5. Android完全組件化—如何使用Arouter

上篇文章講到,AndroidComponent已經進行了UI跳轉的升級改造,能夠支持路由的自動註冊和路由表的自動生成。可是不少使用組件化方案的同窗都表示項目中已經接入ARouter來進行UI跳轉,遷移成本比較高。所以我就專門寫了這篇文章,講解一下如何在組件中使用ARouter。android

不論用DDComponent自帶的方案仍是ARouter,要作到組件之間自由而且可控的跳轉,須要作到下面幾點:git

一、路由跳轉須要支持傳遞基本類型和自定義類型(例如Object) 二、路由的跳轉須要和組件的生命週期一致,即只有加載的組件才能夠跳轉,卸載後的組件是不可達的 三、最好生成路由表,組件對外提供的路由能夠輕鬆查閱到github

下面咱們就從配置開始一步步的講怎麼使用ARouterjson

增長必要的配置

basiclib模塊中增長如下依賴,basiclib是組件化框架中共用的依賴庫:api

compile 'com.alibaba:arouter-api:1.3.0'
複製代碼

在跳轉的目標組件的build.gradle中,增長如下配置:bash

android {
    defaultConfig {
	...
	javaCompileOptions {
	    annotationProcessorOptions {
		arguments = [ moduleName : project.getName() ]
	    }
	}
    }
}
dependencies {
    annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
    ...
}
複製代碼

在組件化框架中,咱們的示例是從readercomponent跳轉到sharecomponent,因此上述配置增長在sharecomponent下面的build.gradle中。app

在目標頁面增長相應的註解

咱們以「分享圖書」 頁面爲例框架

@Route(path = "/share/shareBook")
public class ShareActivity extends AppCompatActivity {
複製代碼

在進入這個頁面,須要傳入兩個參數,一個是String類型的bookName,一個是自定義類型Author的authoride

@Autowired
String bookName;
@Autowired
Author author;
複製代碼

如何傳遞自定義類型

因爲自定義類型Author須要跨組件傳遞,咱們知道,DDComponent的核心之處就是在組件之間見了一堵牆,在編譯期代碼和資源都是徹底隔離的,因此Author必須定義在share組件向外提供的服務中。因此咱們在component中,定義Author類:

public class Author {
    private String name;
    private int age;
    private String county;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getCounty() {
        return county;
    }
    public void setCounty(String county) {
        this.county = county;
    }
}
複製代碼

如今就解決了Author的可見性問題,可是爲了能在路由中傳遞,按照ARouter的要求,還須要本身實現SerializationService:

@Route(path = "/service/json")
public class JsonServiceImpl implements SerializationService {
    @Override
    public void init(Context context) {}
    @Override
    public <t> T json2Object(String text, Class<t> clazz) {
        return JSON.parseObject(text, clazz);
    }
    @Override
    public String object2Json(Object instance) {
        return JSON.toJSONString(instance);
    }
    @Override
    public <t> T parseObject(String input, Type clazz) {
        return JSON.parseObject(input, clazz);
    }
}
複製代碼

這裏筆者就遇到了一個坑,原本我把這個類定義在readercomponent中,結果運行以後會報空指針異常。只有我把類移到sharecomponent以後,異常才消失。暫時沒找到緣由,可是定義在這裏,加入要跳轉到readercomponent怎麼辦呢?

發起跳轉

在組件化框架demo中,發起跳轉是readercomponent中的ReaderFragment中,demo中列出了兩個示例: 普通跳轉

private void goToShareActivityNormal() {
    Author author = new Author();
    author.setName("Margaret Mitchell");
    author.setCounty("USA");
    ARouter.getInstance().build("/share/shareBook")
            .withString("bookName", "Gone with the Wind")
            .withObject("author", author)
            .navigation();
}
複製代碼

以及startActivityForResult

private void goToShareActivityForResult() {
    Author author = new Author();
    author.setName("Margaret Mitchell");
    author.setCounty("USA");
    ARouter.getInstance().build("/share/shareMagazine")
            .withString("bookName", "Gone with the Wind")
            .withObject("author", author)
            .navigation(getActivity(), REQUEST_CODE);
}
複製代碼

控制生命週期

通過上面的操做,已經能夠完成UI跳轉了。可是若是運行demo就能夠發現,此時即便卸載了分享組件,分享書的頁面仍是能夠進入的,說明生命週期沒有同步。在DDComponent自帶的方案中是不存在這個問題的,由於跳轉的邏輯已經與組件化生命週期綁定在一塊兒。 這裏就用到ARouter自帶的攔截器功能,每一個組件都須要定義一個攔截器,當組件卸載以後須要攔截住該組件的跳轉入口。 下面是分享組件攔截器的示例代碼:

@Interceptor(priority = 1, name = "分享組件攔截器")
public class ShareInterceptor implements IInterceptor {
    public static boolean isRegister;
    Context mContext;
    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if (isRegister) {
            callback.onContinue(postcard);
        } else if ("/share/shareBook".equals(postcard.getPath())
                || "/share/shareMagazine".equals(postcard.getPath())) {
            MainLooper.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(mContext, "分享組件已經卸載", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    @Override
    public void init(Context context) {
        mContext = context;
    }
}
複製代碼

這裏經過一個isRegister開關來控制攔截器是否生效,爲了保證生命週期一致性,在ShareApplike中增長賦值邏輯:

public class ShareApplike implements IApplicationLike {
    @Override
    public void onCreate() {
        ShareInterceptor.isRegister = true;
    }
    @Override
    public void onStop() {
        ShareInterceptor.isRegister = false;
    }
}
複製代碼

可是這裏也遇到了兩個小坑,不知道是不是ARouter使用不當: (1)添加或者修改攔截器以後,必須卸載重裝app才能生效,不管是clean仍是rebuild都是不生效的 (2)攔截器中須要硬編碼該組件的全部路由,例如/share/shareBook等,一旦路由發生了改變,必定要記得修改這個地方

路由表生成

這個ARouter暫時沒有提供,DDComponent自帶的方案增長了這個功能,當組件build生成以後,在根目錄生成UIRouterTable文件夾,裏面會列出每一個組件向外提供的路由表以及具體參數

auto generated, do not change !!!! 

HOST : share

分享雜誌頁面
/shareMagazine
author:com.luojilab.componentservice.share.bean.Author
bookName:String

分享書籍頁面
/shareBook
author:com.luojilab.componentservice.share.bean.Author
bookName:String
複製代碼

這點對於組件的協同開發是比較重要的,畢竟跳轉以前翻閱別人的代碼是件比較費事的工做

簡單作一個總結:

  1. ARouter是一個優秀的路由跳轉方案,DDComponent自帶的方案也參考了不少其中的想法,功能很強大
  2. 使用中須要與組件化方案兼容的地方主要是生命週期相關,在攔截器上增長部分邏輯就能夠完成
  3. ARouter使用中還存在一些小的問題,多是姿式不對,接入中走了很多彎路,有熟悉這塊的朋友能夠指出緣由
  4. 路由表沒有自動生成,對外沒有暴露有哪些路由協議和參數,對於組件之間協同開發不太友好

上面的代碼已經發布DDComponent的master-arouter分支,歡迎你們使用,源碼地址: github.com/mqzhangw/An…

相關文章
相關標籤/搜索