Android 多模塊多組件開發(fā) - 打造屬于自己的路由

一.基本介紹

1. 借此機(jī)會(huì)分享一下自己從剛?cè)腴T到現(xiàn)在,在開發(fā)架構(gòu)方面的一些心路歷程。最終我會(huì)把這部分代碼進(jìn)行開源,以后也會(huì)對(duì)其進(jìn)行維護(hù)。但目前尚在測(cè)試中所以并未發(fā)布正式版本。我們可以先把代碼下載下來進(jìn)行了解,如果有什么問題可以隨時(shí) Issues,這也將是我的第一個(gè)開源庫(kù),希望能幫到大家。

2. 該庫(kù)所涉及到的類大概在 30 個(gè)左右,源碼并不多相信我們都能讀懂里面的內(nèi)容,這里羅列一下源碼中所涉及到的一些知識(shí)點(diǎn):
(1) 編譯時(shí)注解自動(dòng)生成 Module、Action 和 Intercepter
(2) 線程、線程池、線程同步異步和 Handler
(3) 責(zé)任鏈模式、享元模式、策略模式、模板模式 ...

3. 作為一個(gè)多模塊的路由通信庫(kù),相信它已支持了所有跨模塊通信的使用場(chǎng)景,功能介紹如下:
(1) 支持依賴注入,可單獨(dú)作為依賴注入框架使用
(2) 支持線程切換和調(diào)度(原始線程,主線程,同步,異步)
(3) 支持多模塊工程下的所有跨模塊通信使用場(chǎng)景
(4) 支持添加多個(gè)攔截器,可根據(jù)優(yōu)先級(jí)自定義攔截順序
(5) 支持權(quán)限和網(wǎng)絡(luò)檢測(cè)、登錄攔截跳轉(zhuǎn)和數(shù)據(jù)埋點(diǎn)等功能

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

二.架構(gòu)的演變之路

首先分享一下自己從剛?cè)腴T到現(xiàn)在,在開發(fā)架構(gòu)方面的一些心路歷程,從剛開始踏上程序這條不歸路(人生就是一條不歸路),想想已經(jīng)是好幾個(gè)年頭,中間經(jīng)歷過提升、迷茫和進(jìn)階,也經(jīng)歷過從不自信到自信、自滿到自負(fù)。剛開始一個(gè)人在小公司小打小鬧,是這個(gè)樣子的:

那個(gè)時(shí)候所有的類都是寫在一個(gè)包下面的,所有的 Activity 都是繼承自系統(tǒng)下的 android.app.Activity,網(wǎng)絡(luò)框架都是直接用的 android-async-http 所以加班挺嚴(yán)重, 一方面是自己能力經(jīng)驗(yàn)還不夠,另一方面是沒有架構(gòu)的情況下很多代碼都是反復(fù)冗余的。畢業(yè)后去了一家上市公司,多人團(tuán)隊(duì)協(xié)作開發(fā)所以就改變了一些:

這個(gè)時(shí)候已經(jīng)有所提升了,所有的 Activity 也不是直接繼承自 android.app.Activity 了,也不再是直接使用 android-async-http 所以開發(fā)的日子自然舒坦了一些。一方面是經(jīng)驗(yàn)?zāi)芰ι先チ擞龅絾栴}能馬上解決,另一方面基于架構(gòu)開發(fā)很多代碼不用反復(fù)寫后期也便于維護(hù),最主要的是大公司人多一些,之前是一個(gè)人干四個(gè)人的活,現(xiàn)在四個(gè)人干一個(gè)人的活。隨著開發(fā)人員的越來越多,還有就是基本每逢過節(jié)都要做一些活動(dòng),等活動(dòng)過后這些代碼和資源就要?jiǎng)h除,而且每?jī)蓚€(gè)月就得迭代一個(gè)新的版本,所以變得越來越復(fù)雜起來。后來就衍生出了很多像熱更新、插件化、多模塊多組件開發(fā)等等。當(dāng)然剛開始的多模塊多組件并未基于路由,是蜘蛛網(wǎng)的狀態(tài)。

會(huì)有這么亂嗎?隨著業(yè)務(wù)邏輯更加復(fù)雜的情況下應(yīng)該會(huì)更亂,因?yàn)楣δ苣K都是各自存在于自己的 Module 中,但是可能在開發(fā)的過程中 Module1 得調(diào)用 Module2 的代碼,這個(gè)時(shí)候如果是直接添加依賴那么肯定就會(huì)有這么亂了。接下來看下基于路由情況下的多模塊多組件開發(fā):

三. DRouter 基本使用

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

    dependencies {
        .......
        annotationProcessor project(':drouter-compiler')
    }
  1. 在 Module 中創(chuàng)建需要執(zhí)行的 Action
// path 必須是以在 gradle 中配置的 moduleName + "/" 開頭,否則編譯通不過。
// threadMode 支持 POSTING 、MAIN、BACKGROUND、ASYNC 默認(rèn)情況下是 POSTING(原始線程)
@Action(path = "login/action", threadMode = ThreadMode.MAIN)
public class LoginAction implements IRouterAction {

    @Override
    public RouterResult invokeAction(Context context, Map<String, Object> requestData) {
        // 通信執(zhí)行方法支持所有場(chǎng)景,啟動(dòng) Activity,Service,Provider,彈框,緩存數(shù)據(jù),獲取 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();
        // 初始化且只能初始化一次,參數(shù)必須是 Application
        DRouter.getInstance().init(this);
    }
}
  1. 可在任意 Module 中執(zhí)行跳轉(zhuǎn)
// 根據(jù) action 查詢只執(zhí)行對(duì)應(yīng)方法,不處理返回回調(diào),參數(shù)攜帶隨意
DRouter.getInstance()
                .action("login/action")
                .context(this)
                .param("key", "value")
                .invokeAction();

// 根據(jù) action 查詢執(zhí)行對(duì)應(yīng)方法,并處理返回回調(diào)
DRouter.getInstance()
                .action("circlemodule/test")
                .context(this)
                .invokeAction(new ActionCallback() {
                    @Override
                    public void onInterrupt() {
                        Log.e("TAG", "被攔截了");
                    }

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

    @Override
    public void intercept(ActionChain chain) {
        ActionPost actionPost = chain.action();
        // 圈子詳情頁(yè)必須是要登錄,如果沒有登錄即可攔截跳轉(zhuǎn)到登錄頁(yè)面,否則繼續(xù)往下執(zhí)行。
        if (chain.actionPath().equals("circlemodule/test")) {
            Toast.makeText(actionPost.context, "攔截圈子,跳轉(zhuǎn)到登錄", Toast.LENGTH_LONG).show();
            // 跳轉(zhuǎn)到登錄頁(yè)面
            DRouter.getInstance()
                    .action("login/action")
                    .context(actionPost.context)
                    .invokeAction();

            // 這個(gè)方法調(diào)用后便會(huì)攔截整條鏈
            chain.onInterrupt();
        }
        // 繼續(xù)向下轉(zhuǎn)發(fā)
        chain.proceed(actionPost);
    }
}

6.混淆配置

-keep public class com.drouter.assist.**{*;}

源碼地址:https://github.com/HCDarren/DRouter
視頻講解:https://pan.baidu.com/s/1kWoIA95

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容