Android點我達路由DRouter框架設計與解析
為什麼要路由
什麼是路由?說簡單點就是對映頁面跳轉關係的,當然它也包含跳轉相關的一切功能。Android系統已經給我們提供了api來做頁面跳轉,比如startActivity,為什麼還需要路由框架呢?我們來簡單分析下路由框架存在的意義:
- 在一些業務場景下,靈活性比較強,很多功能都是運營人員動態配置的,比如下發一個活動頁面,我們事先並不知道具體的目標頁面,但如果事先做了約定,提前做好頁面對映,便可以自由配置。
- 隨著業務量的增長,專案越來越龐大,開發人員越來越多,App一般都會走向元件化、外掛化的道路;而元件化、外掛化的前提就是解耦,那麼我們首先要做的就是解耦頁面之間的依賴關係。
- 極大簡化程式碼。數行跳轉程式碼可以精簡成一行程式碼。
因此我們設計了一個路由框架我們命名為DRouter。總的來說,DRouter設計追求的是功能模組的解耦,能夠實現基本路由功能,以及開發者使用上足夠簡單。DRouter對於使用者來說幾乎是無成本的,只需要在使用路由的頁面定義一個類註解@DRoute即可,頁面路由的使用也相當簡單。
DRouter的特性
- 鏈式呼叫設計,寫法簡單;
- 使用編譯時處理註解生成路由對映表,效能優於執行時處理編譯的路由方案;
- 路由url的設計與常規的http url一致,可以通過query引數傳遞頁面引數;
- 支援通過註解直接注入跳轉引數;
- 支援多個路由url跳轉至同一個頁面;
- 支援路由的正則匹配;
- 支援Activity啟動使用不同的Flag;
- 支援路由的優先順序配置;
- 支援對路由的動態攔截、監聽以及降級;
- 後期將增加action支援,支援通過一個Router連結執行一個方法;
關於DRouter的設計
DRouter URI定義
對於DRouter URI的定義為了使用起來更自然,我們選擇模仿HTTP URI協議: * Scheme的定義目前我們支援dwd、dwd-rider、dwd-shop,當然之後有其它端需要接入時,可以自定義拓展; * Host我們定義了view、action,其中view表示這個是一個頁面跳操作,action表示執行一個method; * Path則是與路由表對應,表示一個頁面或方法; * Query引數與傳統的http get query引數一致,支援拼接基礎資料型別、String、JSON串;
DRouter 執行流程
* 根據解析傳入的DRouter URI建立DRouteRequest物件,並且set呼叫者傳入的callback、flags、requestCode、extras等; * 判斷是否有設定攔截器,如果有設定攔截器則進行執行攔截器方法,本次DRouter執行流程結束,通知呼叫者本次請求被攔截; * 如果沒有攔截器,則與路由表中的path進行匹配,如果匹配通過則Intent構建; * 將引數put到構建完成的Intent中傳到目標頁面;
DRouter的使用
接下來我們來實戰一番,一個Android專案怎麼接入這個DRouter框架,完成路由的生成、跳轉、攔截器的使用等流程。
整合
在工程根目錄的build.gradle中加入:
allprojects { repositories { maven { url "http://192.168.1.31:8081/repository/lib-dwd-snapshots/"} maven { url "http://192.168.1.31:8081/repository/lib-dwd-releases/"} }}
在需要使用module build.gradle中加入:
defaultConfig { javaCompileOptions { annotationProcessorOptions { arguments = ["moduleName": project.name] } } } dependencies { compile 'com.dwd.drouter:routercenter:1.0.1' annotationProcessor 'com.dwd.drouter:compiler:1.0.0' }
OK,這樣你的工程裡面就可以使用DRouter了;
使用
一行程式碼完成各種複雜的跳轉:
DRouter.with(context).load(uri).extra("name","張三").launch();
鏈式api,清晰明瞭,使用簡單,當然要達到這麼有B格的跳轉還是得先做點基建工作;
1、初始化DRouter
在你的Application中的onCreate方法中加入:
public void onCreate() { //這裡要加入所有使用DRouter的module name DRouter.init("module1", "module2", ...); }
2、通過註解建立路由表
在你需要Router化的頁面使用@DRoute(path="/main")註解來為這個頁面在路由表建立一個path:
@DRoute(path="/main") public class MainActivity extends Activity{ @override public void onCreate(Bundle args) { super.onCreate(args); } }
沒錯,只要這麼一個註解,你這個頁面就完成Router化了;
3、建立並使用interceptor
在很多時候,我們在開啟一個頁,必須先登陸,這個時候我們總不可能在每次跳轉一個頁面前先判斷一下是否登陸、執行登陸邏輯,因此我們就引入攔截器,那麼怎麼建立interceptor呢?也很簡單:
@Interceptor("login") public class LoginInterceptor implements DRouteInterceptor{ @Override public boolean intercept(@Nullable Object source, DRouteRequest routeRequest) { if (source instanceof Context && !BaseApplication.getInstance().isLogin()) { DRouter.with((Context) source) .load(Uri.parse("dwd://view/login")) .extra("routerUrl", routeRequest.getUri().toString()) .launch(); return true; } return false; } }
這是一個比較典型的登陸interceptor,邏輯很簡單,就是判斷是否有登陸,如果沒有登陸,就跳轉到登陸介面,並且目標頁面的routerUrl傳遞過去,使得登陸成功後可以繼續跳轉到目標頁面,然後return true表示這個router跳轉被攔截了;
那麼interceptor建立好之後怎麼使用它呢?其實也很簡單,只需要在DRoute註解的interceptor引數中設定好你的登陸interceptor即可:
@DRoute(path="/main", interceptor="login") public class MainActivity extends Activity{ @override public void onCreate(Bundle args) { super.onCreate(args); } }
4、通過註解注入引數
一般跳轉到一個頁面都是需要傳入引數的,使用DRouter你可以直接使用註解注入引數,所有的引數DRouter會通過編譯時處理註解方式自動注入到目標頁面,在不降低效能的情況下極大減少了你的程式碼量,具體用法如下:
@DRoute(path="/main", interceptor="login") public class MainActivity extends Activity{ @Param(key = "name") String name; @override public void onCreate(Bundle args) { super.onCreate(args); DRouter.injectParams(this); } }
總結
DRouter目前是一個很輕巧、簡單、清晰的路由框架、可以將Push、Weex、H5與Native端之間的相互跳轉無縫的整合在一起,當然目前也存在很多待優化的地方,我也會逐步的去優化完善它。