Android组件化设计

作者: 吃泥巴的猫 | 来源:发表于2018-12-09 17:51 被阅读31次

随着app迭代,以及功能需求的更新,项目中的冗余代码量增多,代码各模块间的耦合增强,不利于更新以及测试,所以开始了组建化的设计。

android的组件化基于module的两种属性
application属性,module可以作为独立的app运行
apply plugin: ‘com.android.application’
library属性,module不可独立运行,作为依赖库文件
apply plugin: ‘com.android.library’
通过控制module的此属性可以间module在app以及依赖库之间进行切换,此属性在build.gradle文件中。
而且项目的gradle文件是可以公用的,所以可以新建一个config.gradle文件进行对module以及一些依赖进行配置。

/**
 *  全局统一配置文件
 */
ext {
    //true 每个业务Module可以单独开发
    //false 每个业务Module以lib的方式运行
    //修改之后需要Sync方可生效
    isModule = false

    //版本号
    versions = [
            applicationId           : "com.example.bwq.moduletest",        //应用ID
            versionCode             : 1,                    //版本号
            versionName             : "1.0.0",              //版本名称

            compileSdkVersion       : 28,
            buildToolsVersion       : "27.0.3",
            minSdkVersion           : 16,
            targetSdkVersion        : 28,

            androidSupportSdkVersion: "28.+",
            constraintLayoutVersion : "1.1.3",
            runnerVersion           : "1.0.2",
            espressoVersion         : "3.0.2",
            junitVersion            : "4.12",

            multidexVersion         : "1.0.2",
            butterknifeVersion      : "8.8.1",
            arouterApiVersion       : "1.4.0",
            arouterCompilerVersion  : "1.2.1",
            arouterannotationVersion: "1.0.4",
            recyclerview            : "28.+",
            cardview                : "28.+",
            //三方依赖的版本控制
    ]
    dependencies = ["appcompat_v7"        : "com.android.support:appcompat-v7:${versions["androidSupportSdkVersion"]}",
                    "constraint_layout"   : "com.android.support.constraint:constraint-layout:${versions["constraintLayoutVersion"]}",
                    "runner"              : "com.android.support.test:runner:${versions["runnerVersion"]}",
                    "espresso_core"       : "com.android.support.test.espresso:espresso-core:${versions["espressoVersion"]}",
                    "junit"               : "junit:junit:${versions["junitVersion"]}",
                    "support_annotations" : "com.android.support:support-annotations:${versions["annotationsVersion"]}",
                    "design"              : "com.android.support:design:${versions["androidSupportSdkVersion"]}",
                    "support-v4"          : "com.android.support:support-v4:${versions["androidSupportSdkVersion"]}",
                    "cardview-v7"         : "com.android.support:cardview-v7:${versions["androidSupportSdkVersion"]}",
                    "recyclerview-v7"     : "com.android.support:recyclerview-v7:${versions["androidSupportSdkVersion"]}",

                    //方法数超过65535解决方法64K MultiDex分包方法
                    "multidex"            : "com.android.support:multidex:${versions["multidexVersion"]}",

                    //路由
                    "arouter_api"         : "com.alibaba:arouter-api:${versions["arouterApiVersion"]}",
                    "arouter_compiler"    : "com.alibaba:arouter-compiler:${versions["arouterCompilerVersion"]}",
                    "arouter_annotation"  : "com.alibaba:arouter-annotation:${versions["arouterannotationVersion"]}",

                    //黄油刀
                    "butterknife_compiler": "com.jakewharton:butterknife-compiler:${versions["butterknifeVersion"]}",
                    "butterknife"         : "com.jakewharton:butterknife:${versions["butterknifeVersion"]}",

                    recyclerview          : "com.android.support:recyclerview-v7:${versions["recyclerview"]}",
                    cardview              : "com.android.support:cardview-v7:${versions["cardview"]}",
                    //三方依赖的库地址
    ]
}

其中isModule为控制module为组建模式还是app模式的开关
因此组建module的属性可通过开关来判断,在组建build.gradle文件开头设置为如下:

if (Boolean.valueOf(rootProject.ext.isModule)) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

在组建化中我将app分为三层,
第一层:app层
app入口,初始化页面,以及主页通过在主页viewpager中添加fragment使其成为正常app的主页。
第二层:组建层
将项目按功能划分为各个组建,如登录组建,首页组建,我的组建等,组建间通过路由的方式跳转以及传递数据。
第三层:基础层
项目基础层,公用控件,公用的方法资源文件,网络请求方法,以及依赖库的封装都在这层进行实现。
组建层以及app层的每一个module均依赖基础层,app层依赖每一个组建层以及基础层。
基础层中将在配置文件中的依赖方法,进行依赖,基础层不需要成为app独立运行,因此无需设置application以及library的开关,依赖关键字使用api:

apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
android {
    compileSdkVersion rootProject.ext.versions.compileSdkVersion
    buildToolsVersion rootProject.ext.versions.buildToolsVersion

    defaultConfig {
        minSdkVersion rootProject.ext.versions.minSdkVersion
        targetSdkVersion rootProject.ext.versions.targetSdkVersion
        versionCode rootProject.ext.versions.versionCode
        versionName rootProject.ext.versions.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        //MultiDex分包方法
        multiDexEnabled true

        //Arouter路由配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    //把implementation 用api代替,它是对外部公开的, 所有其他的module就不需要添加该依赖
    api rootProject.ext.dependencies["appcompat_v7"]
    api rootProject.ext.dependencies["constraint_layout"]
    api rootProject.ext.dependencies["cardview-v7"]
    api rootProject.ext.dependencies["recyclerview-v7"]
    api rootProject.ext.dependencies["support-v4"]
    api rootProject.ext.dependencies["design"]
    api rootProject.ext.dependencies["support_annotations"]
    //MultiDex分包方法
    api rootProject.ext.dependencies["multidex"]
    //黄油刀
    annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
    api rootProject.ext.dependencies["butterknife"]
    //Arouter路由
    annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
    api rootProject.ext.dependencies["arouter_api"]
    api rootProject.ext.dependencies["arouter_annotation"]
    api rootProject.ext.dependencies["recyclerview"]
    api rootProject.ext.dependencies["cardview"]
    
}

第二层中因每个组建均需要成为独立app进行测试以及开发,因此,他的manifest文件需要两套,一套为普通library的没有app入口,一套为application的有app入口的文件。
新建module,选择phone&table module,建立标准app module,main包下新建路径manifest放置module作为app时的manifest文件


project显示模式下main文件夹

黄色框为新建文件夹以及新建文件:
manifest配置为基础app配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bwq.main">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/MyAppTheme"
        android:name=".debug.MainApplication">
        <activity android:name=".debug.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

红色框中的manifest文件为library时的

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bwq.main">

    <application>
        <activity android:name=".debug.MainActivity"/>

    </application>

</manifest>

在java中新建debug包,放置一些作为独立app时的配置,如继承自基础层的Application类,如果组建入口为fragment时展示fragment的activity,之后在当前module的builde.gradle中配置

if (Boolean.valueOf(rootProject.ext.isModule)) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}
apply plugin: 'com.jakewharton.butterknife'
android {
    compileSdkVersion rootProject.ext.versions.compileSdkVersion
    buildToolsVersion rootProject.ext.versions.buildToolsVersion

    defaultConfig {
        if (Boolean.valueOf(rootProject.ext.isModule))
            applicationId rootProject.ext.versions.applicationId
        minSdkVersion rootProject.ext.versions.minSdkVersion
        targetSdkVersion rootProject.ext.versions.targetSdkVersion
        versionCode rootProject.ext.versions.versionCode
        versionName rootProject.ext.versions.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        //MultiDex分包方法
        multiDexEnabled true

        //Arouter路由配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        //配置当前module作为app和作为library时的manifest文件以及作为library时所需要忽略的文件
        main {
            if (Boolean.valueOf(rootProject.ext.isModule)) {
                manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    exclude '*debug/**'
                    exclude '*manifest/**'
                }
            }
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //butterKnife
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
    annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
    api project(':basis_library')
}

为了方便组建间的跳转,在基础层中BaseApplication类中初始化路由,BaseApplication为所有组建以及app的Application类的基类。

/**
     * 初始化ARouter
     */
    public void initARouter() {
        if (BuildConfig.DEBUG) {
            ARouter.openLog();
            ARouter.openDebug();
        }
        ARouter.init(instance);
    }

增加组建化后的跳转工具类

public class ARouterUtils {


    /**
     * 根据path返回Fragment
     *
     * @param path path
     * @return fragment
     */
    public static BaseLazyFragment getLazyFragment(String path) {
        return (BaseLazyFragment) ARouter.getInstance()
                .build(path)
                .navigation();
    }

    public static BaseFragment getFragment(String path) {
        return (BaseFragment) ARouter.getInstance()
                .build(path)
                .navigation();
    }

    /**
     * 根据path返回Activity
     *
     * @param path path
     * @return Activity
     */
    public static BaseActivity getActivity(String path) {
        return (BaseActivity) ARouter.getInstance()
                .build(path)
                .navigation();
    }

    /**
     * 根据path返回FragmentActivity
     *
     * @param path path
     * @return FragmentActivity
     */
    public static BaseFragmentActivity getFragmentActivity(String path) {
        return (BaseFragmentActivity) ARouter.getInstance()
                .build(path)
                .navigation();
    }
}

路由跳转URL地址

/**
 * 功能模块入口
 */

public interface ARouterConfig {
    /**
     * 登录页面
     */
    String LOGIN = "/login/LoginActivity";
    /**
     * main
     */
    String MAIN = "/main/MainFragment";
    /**
     * mine
     */
    String MINE = "/mine/MineFragment";
}

app层:
builde.gradle配置:

apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'
android {
    compileSdkVersion rootProject.ext.versions.compileSdkVersion
    buildToolsVersion rootProject.ext.versions.buildToolsVersion
    defaultConfig {
        applicationId rootProject.ext.versions.applicationId
        minSdkVersion rootProject.ext.versions.minSdkVersion
        targetSdkVersion rootProject.ext.versions.targetSdkVersion
        versionCode rootProject.ext.versions.versionCode
        versionName rootProject.ext.versions.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        //MultiDex分包方法
        multiDexEnabled true

        //Arouter路由配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
    annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
    api project(':basis_library')
    if (!Boolean.valueOf(rootProject.ext.isModule)) {
        api project(':main')
        api project(':login')
        api project(':mine')
    }
}

至此,组建化方案完成。

最后说一些注意的问题,各层的依赖关键字需要使用api,不同组建间的资源文件由于在组合后可能会有冲突,各组建间的资源文件建议以组建名开头,如login_back

相关文章

  • Android 组件化规范

    Android 组件化规范 修订记录 目录 组件设计 组件使用 组件升级 组件设计 设计要求 组件必须支持以app...

  • Android 组件化开发实践

    Android组件化开发实践(一):为什么要进行组件化开发?Android组件化开发实践(二):组件化架构设计An...

  • 我所理解的Android组件化之通信机制

    之前写过一篇关于Android组件化的文章, 《Android组件化框架设计与实践》 ,之前没看过的小伙伴可...

  • android 组件化

    Android组件化项目地址:Android组件化项目AndroidModulePattern Android组件...

  • 我所理解的Android组件化之通信机制

    之前写过一篇关于Android组件化的文章,《Android组件化框架设计与实践》,之前没看过的小伙伴可以先点击阅...

  • Android组件化开发原理

    之前写过一篇关于Android组件化的文章,《Android组件化框架设计与实践》,之前没看过的小伙伴可以先点击阅...

  • 我所理解的Android组件化之通信机制

    之前写过一篇关于Android组件化的文章,《Android组件化框架设计与实践》,之前没看过的小伙伴可以先点击阅...

  • Android组件化方案

    Android组件化方案Android彻底组件化demo发布

  • Router方案说明

    前言 该方案是阐述Android平台组件化方案设计中Router 组件的的设计思路。针对猫窝科技组件化开发工作,进...

  • android之组件化

    组件化博客——优秀详解文章 Android组件化项目地址:Android组件化项目AndroidModulePat...

网友评论

    本文标题:Android组件化设计

    本文链接:https://www.haomeiwen.com/subject/whftcqtx.html