组件化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比较简单。
业务module为application时main下新建package mainfest,mainfest下新建配置文件AndroidManifest.xml,目录对应之前配置即可。
6. login module创建成功后,别忘了在app中依赖login。app下build.gralde:
dependencies {
...
if (isLoginModule.toBoolean()) {
implementation project(path: ':login')
}
}
这里说个大概,嫌麻烦也可以看看我的实现:https://github.com/xuanduoduo/MVP