Android 组件化实践

作者: 折剑游侠 | 来源:发表于2019-10-20 14:37 被阅读0次

    组件化MVP+Retrofit+Rxjava,项目使用kotlin,路由框架Arouter。

    1. 新建项目New Project
    2. 根目录创建config.gradle文件,统一管理依赖库。
    ext {
        android = [
                compileSdkVersion: 28,
                applicationId    : "com.chenxuan.kotlinmvp",
                minSdkVersion    : 21,
                targetSdkVersion : 28,
                versionCode      : 1,
                versionName      : "1.0.0",
        ]
    
        versions = [
                kotlin             : "1.3.40",
                androidx_core      : "1.1.0",
                appcompat          : "1.1.0",
                constraintlayout   : "1.1.3",
                rxjava             : "2.2.9",
                rxandroid          : "2.1.1",
                retrofit           : "2.6.0",
                converter_gson     : "2.6.0",
                adapter_rxjava2    : "2.6.0",
                gson               : "2.8.5",
                logging_interceptor: "4.0.0-alpha02",
                utilcodex          : "1.25.9",
                arouter            : "1.5.0",
                arouter_compiler   : "1.2.2",
                autosize           : "1.1.2",
                glide              : "4.9.0",
                glide_compiler     : "4.9.0",
                material_dialogs   : "0.9.6.0",
                logger             : "2.2.0",
                immersionbar       : "3.0.0-beta05",
                recyclerViewAdapter: "2.9.30",
                rxpermissions      : "0.10.2",
                matisse            : "0.5.2-beta3",
                eventbus           : "3.1.1",
                leakcanary         : "2.0-alpha-2",
                leaksentry         : "2.0-alpha-2",
                multidex           : "1.0.3"
        ]
    
        dependencies = [
                kotlin             : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$versions.kotlin",
                androidx_core      : "androidx.core:core-ktx:$versions.androidx_core",
                appcompat          : "androidx.appcompat:appcompat:$versions.appcompat",
                constraintlayout   : "androidx.constraintlayout:constraintlayout:$versions.constraintlayout",
                rxjava             : "io.reactivex.rxjava2:rxjava:$versions.rxjava",
                rxandroid          : "io.reactivex.rxjava2:rxandroid:$versions.rxandroid",
                retrofit           : "com.squareup.retrofit2:retrofit:$versions.retrofit",
                converter_gson     : "com.squareup.retrofit2:converter-gson:$versions.converter_gson",
                adapter_rxjava2    : "com.squareup.retrofit2:adapter-rxjava2:$versions.adapter_rxjava2",
                gson               : "com.google.code.gson:gson:$versions.gson",
                logging_interceptor: "com.squareup.okhttp3:logging-interceptor:$versions.logging_interceptor",
                //AndroidUtilCode---https://github.com/Blankj/AndroidUtilCode
                utilcodex          : "com.blankj:utilcodex:$versions.utilcodex",
                //ARouter---https://github.com/alibaba/ARouter/blob/master/README_CN.md
                arouter            : "com.alibaba:arouter-api:$versions.arouter",
                arouter_compiler   : "com.alibaba:arouter-compiler:$versions.arouter_compiler",
                //屏幕适配---https://github.com/JessYanCoding/AndroidAutoSize
                autosize           : "me.jessyan:autosize:$versions.autosize",
                //glide---https://github.com/bumptech/glide
                glide              : "com.github.bumptech.glide:glide:$versions.glide",
                glide_compiler     : "com.github.bumptech.glide:compiler:$versions.glide_compiler",
                //dialog---https://github.com/afollestad/material-dialogs
                material_dialogs   : "com.afollestad.material-dialogs:commons:$versions.material_dialogs",
                //日志---https://github.com/orhanobut/logger
                logger             : "com.orhanobut:logger:$versions.logger",
                //状态栏---https://github.com/gyf-dev/ImmersionBar
                immersionbar       : "com.gyf.immersionbar:immersionbar:$versions.immersionbar",
                //adapter---https://www.jianshu.com/p/b343fcff51b0
                recyclerViewAdapter: "com.github.CymChad:BaseRecyclerViewAdapterHelper:$versions.recyclerViewAdapter",
                //权限---https://github.com/tbruyelle/RxPermissions
                rxpermissions      : "com.github.tbruyelle:rxpermissions:$versions.rxpermissions",
                //图片选择器---https://github.com/zhihu/Matisse
                matisse            : "com.zhihu.android:matisse:$versions.matisse",
                //EventBus---https://github.com/greenrobot/EventBus
                eventbus           : "org.greenrobot:eventbus:$versions.eventbus",
                //内存泄漏---https://github.com/square/leakcanary/wiki/Migrating-to-LeakCanary-2.0
                leakcanary         : "com.squareup.leakcanary:leakcanary-android:$versions.leakcanary",
                leaksentry         : "com.squareup.leakcanary:leaksentry:$versions.leaksentry",
                //65536分包
                multidex           : "com.android.support:multidex:$versions.multidex"
        ]
    }
    

    打开app下build.gradle修改如下

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-kapt'
    
    def root_android = rootProject.ext.android
    def root_dependencies = rootProject.ext.dependencies
    
    android {
        compileSdkVersion root_android.compileSdkVersion
        defaultConfig {
            applicationId root_android.applicationId
            minSdkVersion root_android.minSdkVersion
            targetSdkVersion root_android.targetSdkVersion
            versionCode root_android.versionCode
            versionName root_android.versionName
            multiDexEnabled true
    
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        kapt root_dependencies.arouter_compiler
    }
    
    

    简单说明下
    def root_android = rootProject.ext.android
    def root_dependencies = rootProject.ext.dependencies

    rootProject.ext.android->config.gradle下android[]
    rootProject.ext.dependencies->confing.gradle下dependencies[]。

    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }
    
    dependencies {
        ...
        kapt root_dependencies.arouter_compiler
    }
    

    这段代码是Arouter配置,无需改动。

    3. 新建base module,选择library。此mudole统一管理依赖库。修改base下build.gradle:
    apply plugin: 'com.android.library'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-kapt'
    
    def root_android = rootProject.ext.android
    def root_dependencies = rootProject.ext.dependencies
    
    android {
        compileSdkVersion root_android.compileSdkVersion
        defaultConfig {
            minSdkVersion root_android.minSdkVersion
            targetSdkVersion root_android.targetSdkVersion
            versionCode root_android.versionCode
            versionName root_android.versionName
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    
    }
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        api root_dependencies.kotlin
        api root_dependencies.androidx_core
        api root_dependencies.appcompat
        api root_dependencies.constraintlayout
        api root_dependencies.rxjava
        api root_dependencies.rxandroid
        api root_dependencies.retrofit
        api root_dependencies.converter_gson
        api root_dependencies.adapter_rxjava2
        api root_dependencies.gson
        api root_dependencies.logging_interceptor
        api root_dependencies.utilcodex
        api root_dependencies.arouter
        kapt root_dependencies.arouter_compiler
        api root_dependencies.autosize
        api root_dependencies.glide
        annotationProcessor root_dependencies.glide_compiler
        api root_dependencies.material_dialogs
        api root_dependencies.logger
        api root_dependencies.immersionbar
        api root_dependencies.recyclerViewAdapter
        api root_dependencies.rxpermissions
        api root_dependencies.matisse
        api root_dependencies.eventbus
        api root_dependencies.multidex
    }
    

    这里用api引入依赖,其它moudle依赖base后也能使用这些依赖库。

    4. 新建common module,选择library。此module封装项目基本框架,MVP、网络库等。修改common下build.gradle:
    apply plugin: 'com.android.library'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    
    def root_android = rootProject.ext.android
    
    android {
        compileSdkVersion root_android.compileSdkVersion
        defaultConfig {
            minSdkVersion root_android.minSdkVersion
            targetSdkVersion root_android.targetSdkVersion
            versionCode root_android.versionCode
            versionName root_android.versionName
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        api project(path: ':base')
    }
    

    api project(path: ':base')

    common依赖base,可使用base下依赖库,不清楚的可以查看api和implementation区别。这里引入base使用api,业务moudle引入common也可使用base下依赖库。

    接下来在common中写mvp框架,网络框架,utils等。复杂的功能,如网络框架可以单独抽出来,写成net module。

    5. 业务module,新建login module。根目录下gradle.properties新增变量isLoginModule=true。
    # Project-wide Gradle settings.
    # IDE (e.g. Android Studio) users:
    # Gradle settings configured through the IDE *will override*
    # any settings specified in this file.
    # For more details on how to configure your build environment visit
    # http://www.gradle.org/docs/current/userguide/build_environment.html
    # Specifies the JVM arguments used for the daemon process.
    # The setting is particularly useful for tweaking memory settings.
    org.gradle.jvmargs=-Xmx1536m
    # When configured, Gradle will run in incubating parallel mode.
    # This option should only be used with decoupled projects. More details, visit
    # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
    # org.gradle.parallel=true
    # AndroidX package structure to make it clearer which packages are bundled with the
    # Android operating system, and which are packaged with your app's APK
    # https://developer.android.com/topic/libraries/support-library/androidx-rn
    android.useAndroidX=true
    # Automatically convert third-party libraries to use AndroidX
    android.enableJetifier=true
    # Kotlin code style for this project: "official" or "obsolete":
    kotlin.code.style=official
    #控制module true为library,false为application
    isLoginModule=true
    

    修改login下build.gradle:

    if (isLoginModule.toBoolean()) {
        apply plugin: 'com.android.library'
    } else {
        apply plugin: 'com.android.application'
    }
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-kapt'
    
    def root_android = rootProject.ext.android
    def root_dependencies = rootProject.ext.dependencies
    
    android {
        compileSdkVersion root_android.compileSdkVersion
        defaultConfig {
            minSdkVersion root_android.minSdkVersion
            targetSdkVersion root_android.targetSdkVersion
            versionCode root_android.versionCode
            versionName root_android.versionName
    
            if (!isLoginModule.toBoolean()) {
                //单独运行时需要applicationId 
                applicationId "com.chenxuan.kotlinmvp.login"
            }
        }
    
        sourceSets {
            main {
                //使用不同的 AndroidManifest.xml 文件
                if (isLoginModule.toBoolean()) {
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                } else {
                    manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
                }
            }
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    
    }
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation project(path: ':common')
        kapt root_dependencies.arouter_compiler
    }
    

    通过isLoginModule控制业务module是否作为application单独编译运行。isLoginModule写在gradle.properties文件中每次修改都会触发编译。

    if (isLoginModule.toBoolean()) {
        apply plugin: 'com.android.library'
    } else {
        apply plugin: 'com.android.application'
    }
    
    android {
        defaultConfig {
            ...
            if (!isLoginModule.toBoolean()) {
                //单独运行时需要applicationId
                applicationId "com.chenxuan.kotlinmvp.login"
            }
        }
    }
    

    业务module为library/application时Manifest文件配置有差异,appapplication需要配置启动项,指定application等。

    sourceSets {
            main {
                //使用不同的 AndroidManifest.xml 文件
                if (isLoginModule.toBoolean()) {
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                } else {
                    manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
                }
            }
        }
    

    在对应目录新建配置文件AndroidManifest.xml。业务module为library时,main下AndroidManifest.xml比较简单。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.chenxuan.login">
    
        <application android:allowBackup="true">
    
            <activity android:name=".ui.LoginActivity" />
        </application>
    
    </manifest>
    

    业务module为application时main下新建package mainfest,mainfest下新建配置文件AndroidManifest.xml,目录对应之前配置即可。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              package="com.chenxuan.login">
    
        <application
                android:allowBackup="true"
                android:name="com.chenxuan.common.base.BaseApplication"
                android:icon="@mipmap/ic_launcher"
                android:label="@string/app_name"
                android:roundIcon="@mipmap/ic_launcher_round"
                android:supportsRtl="true"
                android:theme="@style/AppTheme"
                tools:ignore="GoogleAppIndexingWarning">
            <activity android:name="com.chenxuan.login.ui.LoginActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    
    6. login module创建成功后,别忘了在app中依赖login。app下build.gralde:
    dependencies {
        ...
        if (isLoginModule.toBoolean()) {
            implementation project(path: ':login')
        }
    }
    

    这里说个大概,嫌麻烦也可以看看我的实现:https://github.com/xuanduoduo/MVP

    相关文章

      网友评论

        本文标题:Android 组件化实践

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