1. 程式人生 > >Android業務元件化之子模組SubModule的拆分以及它們之間的路由Router實現

Android業務元件化之子模組SubModule的拆分以及它們之間的路由Router實現

前言:

     前面分析了APP的現狀以及業務元件化的一些探討(Android業務元件化之現狀分析與探討),以及通訊的橋樑Scheme的使用(Android業務元件化之URL Scheme使用),今天重點來聊下子模組SubModule的拆分以及它們之間的路由Router實現。本篇涉及的相關知識比較多,閱讀本篇之間需要大致瞭解一下Java的註解(Java學習之註解Annotation實現原理)、Java的動態代理機制(Java設計模式之代理模式(Proxy))等。業務元件化是一個循序漸進的過程,一開始很難就能拿出終極解決方案,還是一步步來走的比較踏實實在。

   業務元件化相關文章地址:

我們首先搞清楚什麼是業務元件?

    搞清楚這個對我們來說至關重要,否則很難拆分業務與依賴庫,也很難搞清楚哪些類應該放在業務子模組裡面哪些類應該放在依賴庫裡面。

 1.)和業務無關

     完全和業務沒有一點關係,比如專案中常用的各種Utils工具類,一些公共自定義控制元件例如顯示圓角圖片的ImageView等

 2.)弱業務

    為什麼稱之為弱業務,原因就是這些不是完整的業務,但是又和APP業務相關,比如我們的網路請求,資料庫操作等。

 3.)業務

   這個就是我們針對要拆分的業務元件,一個完整的獨立的業務線才能稱之為業務,比如我們APP的登入註冊業務等。

業務元件的拆分粒度?

    業務元件的拆分將是整個整改的重點,關於拆分的粒度也將成為討論的焦點,到底是粗一點好還是細一點好?粗一點更容易拆分,細一點更容易解耦靈活度高,這個根據實際情況來定,由於我們專案整改的過程中不能影響到新需求的開發,開始還是以粗一點的粒度進行拆分,先把大致幾個業務拆分出來,後期慢慢再做細。

子模組SubModule拆分:

1.)子模組沒有拆分之間

  頁面跳轉

Intent intent = new Intent(this, XXX.class);
startActivity(intent);

 資料傳遞

  直接頁面startActivityForResult返回獲取, 間接頁面通過儲存或者變數 ,或者藉助開源框架EventBus等傳遞

沒有拆分的這種開發方式,其實使用起來簡單方便,但是這種顯示呼叫沒有任務文件,每一個跳轉頁面都要和相關開發人員溝通,溝通成本比較高。

2.)拆分子模組之後

 拆分子模組之後,任何模組之間的跳轉都要採用路由Router中轉,需要在相關Activity中配置如下資訊

        <activity
            android:name=".GoodsDetailActivity"
            android:theme="@style/AppTheme">
            <intent-filter>
                <data
                    android:host="goods"
                    android:path="/goodsDetail"
                    android:port="8888"
                    android:scheme="xl"/>
                <category android:name="android.intent.category.DEFAULT"/>

                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.BROWSABLE"/>
            </intent-filter>
        </activity>

頁面跳轉

    /**
     * 通過uri跳轉指定頁面
     *
     * @param url
     */
    private void openRouterUri(String url) {
        PackageManager packageManager = mContext.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
        boolean isValid = !activities.isEmpty();
        if (isValid) {
            mContext.startActivity(intent);
        }
    }

資料的傳遞同樣可以直接頁面startActivityForResult返回獲取, 間接頁面通過儲存或者變數 ,或者藉助開源框架EventBus等傳遞,但是這些弱業務公共資料統一放在依賴庫裡。模組之間不存在程式碼引用。通過這種方式android,iOS與H5客戶端可以通過一些簡單的url來實現跳轉了,通維護一份文件來約束各個頁面的引數。

3.)路由Router簡單實現

   1.定義兩個註解引數,一個標示URI註解,一個標示引數

RouterUri.java
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface RouterUri {

    String routerUri() default "";

}
RouterParam.java
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface RouterParam {
    
    String value() default "";
    
}

 2.定義一個URI協議介面

IRouterUri.java
public interface IRouterUri {

    @RouterUri(routerUri = "xl://goods:8888/goodsDetail")//請求Url地址
    void jumpToGoodsDetail(@RouterParam("goodsId") String goodsId, @RouterParam("des") String des);//引數商品Id 商品描述

}

3.定義一個單例,內部通過動態代理機制實現跳轉

public class XLRouter {
    private final static String TAG = XLRouter.class.getSimpleName();
    private static IRouterUri mRouterUri;
    private static Context mContext;


    /**
     * 初始化
     */
    public static void initXLRouter(Context context) {
        mContext = context.getApplicationContext();
        mRouterUri = create(IRouterUri.class);
    }

    /**
     * 返回Api
     */
    public static IRouterUri routerUri() {
        return mRouterUri;
    }

    private static IRouterUri create(Class<?> aClass) {
        return (IRouterUri) Proxy.newProxyInstance(aClass.getClassLoader(), new Class<?>[]{aClass},
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
                        StringBuilder stringBuilder = new StringBuilder();
                        RouterUri reqUrl = method.getAnnotation(RouterUri.class);
                        Log.e(TAG, "IReqApi---reqUrl->" + reqUrl.routerUri());
                        stringBuilder.append(reqUrl.routerUri());
                        //Type[] parameterTypes = method.getGenericParameterTypes();//獲取註解引數型別
                        Annotation[][] parameterAnnotationsArray = method.getParameterAnnotations();//拿到引數註解
                        //Annotation[] annotation = method.getDeclaredAnnotations();
                        int pos = 0;
                        for (int i = 0; i < parameterAnnotationsArray.length; i++) {
                            Annotation[] annotations = parameterAnnotationsArray[i];
                            if (annotations != null && annotations.length != 0) {
                                if (pos == 0) {
                                    stringBuilder.append("?");
                                } else {
                                    stringBuilder.append("&");
                                }
                                pos++;
                                RouterParam reqParam = (RouterParam) annotations[0];
                                stringBuilder.append(reqParam.value());
                                stringBuilder.append("=");
                                stringBuilder.append(args[i]);
                                Log.e(TAG, "reqParam---reqParam->" + reqParam.value() + "=" + args[i]);
                            }
                        }
                        //下面就可以執行相應的跳轉操作
                        openRouterUri(stringBuilder.toString());
                        return null;
                    }
                });
    }

    /**
     * 通過uri跳轉指定頁面
     *
     * @param url
     */
    private static void openRouterUri(String url) {
        PackageManager packageManager = mContext.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
        boolean isValid = !activities.isEmpty();
        if (isValid) {
            mContext.startActivity(intent);
        }
    }
}

4.)在進行XLRouter初始化

XLRouter.initXLRouter(this);

5.呼叫方式

XLRouter.routerUri().jumpToGoodsDetail("1000110002","goods des");

總結:

   要實現真正的業務元件化任重而道遠,我們這裡實現第一步拆分子模組,讓各個模組的程式碼各自維護,先解耦他們之間的依賴關係,在app殼工程通過compile project(':umeng_social_sdk_library')這種方式選擇性接入哪個子模組,開發過程中開發哪個模組就引入哪個模組,測試環節也是如此,測試哪個模組打包引入哪個模組,最終測試需要引入全部相關模組,測試上線。

相關推薦

Android業務元件模組SubModule拆分以及它們之間路由Router實現

前言:      前面分析了APP的現狀以及業務元件化的一些探討(Android業務元件化之現狀分析與探討),以及通訊的橋樑Scheme的使用(Android業務元件化之URL Scheme使用),今天重點來聊下子模組SubModule的拆分以及它們之間的路由Router實現。本篇涉及的相關知識比較多,閱讀

Android業務元件現狀分析與探討

前言:       從個人經歷來說的話,從事APP開發這麼多年來,所接觸的APP的體積變得越來越大,業務的也變得越來越複雜,總來來說只有一句話:這是一個APP臃腫的時代!所以為了告別APP臃腫的時代,讓我們進入一個U盤時代,每個業務模組都是一個具備獨立執行的U盤,插在哪

Android業務元件Gradle和Sonatype Nexus搭建私有maven倉庫

前言:      公司的業務元件化推進的已經差不多三四個月的時間了,各個業務元件之間的解耦工作已經基本完成,各個業務元件以module的形式存在專案中,然後專案依賴本地的module,多少有點不太利於專案的並行開發維護了,本質原因就是如果是依賴本地的,必須要將依賴的module和主工程放在一個project裡

Android業務元件URL Scheme使用

前言:      最近公司業務發展迅速,單一的專案工程不再適合公司發展需要,所以開始推進公司APP業務元件化,很榮幸自己能夠牽頭做這件事,經過研究實現元件化的通訊方案通過URL Scheme,所以想著現在還是在預研階段,很有必要先了解一下URL Scheme,看看是如何使用的?其實在之前做Hybrid混合程

Android元件不同模組間 互動(activity互相跳轉,資料互相傳遞,互相呼叫函式)

 轉載請標明地址:https://blog.csdn.net/gaolei1201/article/details/77601027 在元件化之前,業務發展不是很快的時候,這樣是比較合適的,能一定程度地保證開發效率。 慢慢地程式碼量多了起來,開發人員也多了起來,業務發展也

Android 專案元件建立module,生成aar,引入aar

導言: 在android平時的開發中,經常自己寫的東西讓別人使用,那麼就有module,aar,jar等方式. 1:module通過import module並dependencies完成 2:aar,包括所有檔案的android專用包,通過右邊的gradle->assembl

Android 業務元件開發實踐

本文原創,轉載請以連結形式註明地址:http://kymjs.com/code/2016/10/18/01元件化並不是新話題,其實很早很早以前我們開始為專案解耦的時候就討論過的。但那時候我們說的是功能元件化。比如很多公司都常見的,網路請求模組、登入註冊模組單獨拿出來,交給一個團隊開發,而在用的時候只需要接入對

Android業務元件開發實踐

1. 寫在前面 原文地址:http://kymjs.com/code/2016/10/18/01 借用阿布倪盟博的一句話:“在MDCC中馮森林老師的《迴歸初心,從容器化到元件化》,為我們這些沒有那麼多精力折騰黑科技開發者們打開了另一扇門” 。 元件

Android業務元件開發實踐(轉載)

借用阿布倪盟博的一句話:“在MDCC中馮森林老師的《迴歸初心,從容器化到元件化》,為我們這些沒有那麼多精力折騰黑科技開發者們打開了另一扇門” 。 元件化並不是新話題,其實很早很早以前我們開始為專案解耦的時候就討論過的。但那時候我們說的是功能元件化。比如很多公司都常

Android業務元件開發實踐(二)

前言:       從個人經歷來說的話,從事APP開發這麼多年來,所接觸的APP的體積變得越來越大,業務的也變得越來越複雜,總來來說只有一句話:這是一個APP臃腫的時代!所以為了告別APP臃腫的時代,讓我們進入一個U盤時代,每個業務模組都是一個具備獨立執行的U盤,插在哪裡都可以完美執行,這就是推進業務元件

Android專案架構業務元件

前言: 從個人經歷來說的話,從事APP開發這麼多年來,所接觸的APP的體積變得越來越大,業務的也變得越來越複雜,總來來說只有一句話:這是一個APP臃腫的時代!所以為了告別APP臃腫的時代,讓我們進入一個U盤時代,每個業務模組都是一個具備獨立執行的盤,插在哪裡都

Android元件元件通訊

Demo地址:https://github.com/751496032/ComponentDemo 本文是續上一篇Android元件化方案實踐與思考文章一些思考,主要是針對元件間通訊,比如: 每個元件如何初始化各自的資料 Activity間如何跳轉、Fragment例項

我所理解的Android元件通訊機制

之前寫過一篇關於Android元件化的文章,《Android元件化框架設計與實踐》,之前沒看過的小夥伴可以先點選閱讀。那篇文章是從實戰中進行總結得來,是公司的一個真實專案進行元件化架構改造,粒度會分的更粗些,是對整體架構實踐進行相應的總結,裡面說了要打造一個元件化框架的話,需要從以下7個方面入手: 程式碼解

Android 元件路由設計

基於公司業務發展,公司的APP需求不斷增加,應用也略顯“臃腫”。想著趁現在不那麼“糟糕”,時間也比較寬裕,把專案結構整整,因而走上了元件化之路。 模組化 VS 元件化 模組化: 將一個程式按照其功能做拆分,分成相互獨立的模組,以便於每個模組只包含與其功能

Android元件終極方案

Fragment或View如何支援元件化 距離 Android元件化方案 釋出已經半年有餘,雖說這個方案已經能夠解決一些專案的需求,但是依然不夠完美。很多開發者也在部落格和GitHub中留言甚至發郵件問我,Fragment怎麼辦?

(一)Android官方MVVM框架實現元件整體結構

一、google官方MVVM框架講解 我前面對比了MVC和MVP《兩張圖看懂Android開發中MVC與MVP的區別》,可以相對於MVC我們的MVP是有多優越,但是Android開發現在已經開始流行了MVVM,前不久google官方釋出了MVV

Android業務組件Gradle和Sonatype Nexus搭建私有maven倉庫

Android 前言: 公司的業務組件化推進的已經差不多三四個月的時間了,各個業務組件之間的解耦工作已經基本完成,各個業務組件以module的形式存在項目中,然後項目依賴本地的module,多少有點不太利於項目的並行開發維護了,本質原因就是如果是依賴本地的,必須要將依賴

Android組件終極方案

string 問題 我想 ont 建倉 組織 net 直接 互聯網技術 Android組件化項目地址:Android組件化項目AndroidModulePattern Fragment或View如何支持組件化 如何管理組件 Fragment或View如何

IView元件部署

IView是什麼? iView 是一套基於 Vue.js 的開源 UI 元件庫,主要服務於 PC 介面的中後臺產品。 Npm安裝IView npm install iview 在main.js中配置Iview // The Vue build version to load

元件路—整合元件SDK

介紹 元件化的前提是要有基礎元件、功能元件、業務元件這三大塊。其中基礎元件和功能元件都可以做成SDK,可以供其他APP選擇性的呼叫。 比如把地圖元件單獨封裝成一個SDK,需要使用地圖就載入這個SDK,不需要使用的就不載入。對於全部封裝成一個公共庫的做法,這樣既能實現解耦,又可以減少包的大