Android 多模塊多組件開發 - 打造屬於本身的路由

一.基本介紹

1. 藉此機會分享一下本身從剛入門到如今,在開發架構方面的一些心路歷程。最終我會把這部分代碼進行開源,之後也會對其進行維護。但目前尚在測試中因此並未發佈正式版本。咱們能夠先把代碼下載下來進行了解,若是有什麼問題能夠隨時 Issues,這也將是個人第一個開源庫,但願能幫到你們。java

2. 該庫所涉及到的類大概在 30 個左右,源碼並很少相信咱們都能讀懂裏面的內容,這裏羅列一下源碼中所涉及到的一些知識點: (1) 編譯時註解自動生成 Module、Action 和 Intercepter (2) 線程、線程池、線程同步異步和 Handler (3) 責任鏈模式、享元模式、策略模式、模板模式 ...android

3. 做爲一個多模塊的路由通訊庫,相信它已支持了全部跨模塊通訊的使用場景,功能介紹以下: (1) 支持依賴注入,可單獨做爲依賴注入框架使用 (2) 支持線程切換和調度(原始線程,主線程,同步,異步) (3) 支持多模塊工程下的全部跨模塊通訊使用場景 (4) 支持添加多個攔截器,可根據優先級自定義攔截順序 (5) 支持權限和網絡檢測、登陸攔截跳轉和數據埋點等功能git

4. 筆者閱讀了大量的開源庫源碼,本庫的全部代碼思想都來自其中,很感激這些大牛的開源和分享精神: (1) ARouter (2) butterknife (3) okhttp (4) EventBus (5) RxJava (6) retrofitgithub

二.架構的演變之路

首先分享一下本身從剛入門到如今,在開發架構方面的一些心路歷程,從剛開始踏上程序這條不歸路(人生就是一條不歸路),想一想已是好幾個年頭,中間經歷過提高、迷茫和進階,也經歷過從不自信到自信、自滿到自負。剛開始一我的在小公司小打小鬧,是這個樣子的:緩存

那個時候全部的類都是寫在一個包下面的,全部的 Activity 都是繼承自系統下的 android.app.Activity,網絡框架都是直接用的 android-async-http 因此加班挺嚴重, 一方面是本身能力經驗還不夠,另外一方面是沒有架構的狀況下不少代碼都是反覆冗餘的。畢業後去了一家上市公司,多人團隊協做開發因此就改變了一些:bash

這個時候已經有所提高了,全部的 Activity 也不是直接繼承自 android.app.Activity 了,也再也不是直接使用 android-async-http 因此開發的日子天然舒坦了一些。一方面是經驗能力上去了遇到問題能立刻解決,另外一方面基於架構開發不少代碼不用反覆寫後期也便於維護,最主要的是大公司人多一些,以前是一我的幹四我的的活,如今四我的幹一我的的活。隨着開發人員的愈來愈多,還有就是基本每逢過節都要作一些活動,等活動事後這些代碼和資源就要刪除,並且每兩個月就得迭代一個新的版本,因此變得愈來愈複雜起來。後來就衍生出了不少像熱更新、插件化、多模塊多組件開發等等。固然剛開始的多模塊多組件並未基於路由,是蜘蛛網的狀態。網絡

會有這麼亂嗎?隨着業務邏輯更加複雜的狀況下應該會更亂,由於功能模塊都是各自存在於本身的 Module 中,可是可能在開發的過程當中 Module1 得調用 Module2 的代碼,這個時候若是是直接添加依賴那麼確定就會有這麼亂了。接下來看下基於路由狀況下的多模塊多組件開發:架構

三. DRouter 基本使用

  1. 在須要跨模塊通訊的Module中添加依賴和配置
defaultConfig {
        ......
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }
    }

    dependencies {
        .......
        annotationProcessor project(':drouter-compiler')
    }
複製代碼
  1. 在 Module 中建立須要執行的 Action
// path 必須是以在 gradle 中配置的 moduleName + "/" 開頭,不然編譯通不過。
// threadMode 支持 POSTING 、MAIN、BACKGROUND、ASYNC 默認狀況下是 POSTING(原始線程)
@Action(path = "login/action", threadMode = ThreadMode.MAIN)
public class LoginAction implements IRouterAction {

    @Override
    public RouterResult invokeAction(Context context, Map<String, Object> requestData) {
        // 通訊執行方法支持全部場景,啓動 Activity,Service,Provider,彈框,緩存數據,獲取 Fragment 等等等等
        Intent intent = new Intent(context, LoginActivity.class);
        intent.putExtra("key", (String) requestData.get("key"));
        context.startActivity(intent);
        return new RouterResult.Builder().success().object(100).build();
    }
}
複製代碼
  1. 初始化 SDK
public class BaseApplication extends Application{
    @Override
    public void onCreate() {
        super.onCreate();
        // 開啓 debug
        DRouter.openDebug();
        // 初始化且只能初始化一次,參數必須是 Application
        DRouter.getInstance().init(this);
    }
}
複製代碼
  1. 可在任意 Module 中執行跳轉
// 根據 action 查詢只執行對應方法,不處理返回回調,參數攜帶隨意
DRouter.getInstance()
                .action("login/action")
                .context(this)
                .param("key", "value")
                .invokeAction();

// 根據 action 查詢執行對應方法,並處理返回回調
DRouter.getInstance()
                .action("circlemodule/test")
                .context(this)
                .invokeAction(new ActionCallback() {
                    @Override
                    public void onInterrupt() {
                        Log.e("TAG", "被攔截了");
                    }

                    @Override
                    public void onResult(RouterResult result) {
                        // 注意該方法的執行線程是由 Action 的 threadMode 決定的,也就是說和 Action 在同一個線程
                        Log.e("TAG", "result = " + result.toString());
                    }
                });
複製代碼
  1. 在任意模塊下均可添加攔截
// priority 優先級越高,攔截器執行越優先
@Interceptor(priority = 18)
public class CircleInterceptor implements ActionInterceptor {

    @Override
    public void intercept(ActionChain chain) {
        ActionPost actionPost = chain.action();
        // 圈子詳情頁必須是要登陸,若是沒有登陸便可攔截跳轉到登陸頁面,不然繼續往下執行。
        if (chain.actionPath().equals("circlemodule/test")) {
            Toast.makeText(actionPost.context, "攔截圈子,跳轉到登陸", Toast.LENGTH_LONG).show();
            // 跳轉到登陸頁面
            DRouter.getInstance()
                    .action("login/action")
                    .context(actionPost.context)
                    .invokeAction();

            // 這個方法調用後便會攔截整條鏈
            chain.onInterrupt();
        }
        // 繼續向下轉發
        chain.proceed(actionPost);
    }
}
複製代碼

6.混淆配置app

-keep public class com.drouter.assist.**{*;}
複製代碼

源碼地址:https://github.com/HCDarren/DRouter框架

視頻講解:https://pan.baidu.com/s/1kWoIA95

相關文章
相關標籤/搜索