从今天开始带大家一起从零开始撸一个美团Android版App。 【从零撸美团】这个专题将持续更新,用以详细记录分享开发过程,欢迎关注。
源码地址:https://github.com/cachecats/LikeMeiTuan
专题的第一篇文章本来想按惯例讲项目介绍、整体架构、代码规范之类的。但今天有点躁动,不想讲那么正经深奥的东西,定的最低计划又是周三和周日每周两更,所以就暂且讲构建项目依赖的小技巧吧。项目架构稍后会补上~
如果项目比较小,架构简单只有一个 build.gradle
文件那完全不必将依赖抽离出来,因为整个系统构建好还是要费一些精力的。不是一直喊避免过度设计吗?
但是如果按照著名的 Android-CleanArchitecture
(https://github.com/android10/Android-CleanArchitecture) 介绍的架构对项目进行分层,整个项目会有好几个 module
。
先贴出 Clean architecture 的架构图感受下~
基于这个分层思想,我的项目结构是这样的:
项目一共分为四层 common
: 整个依赖的最底层,抽取出其他层共有的代码。比如 RxJava的封装,工具类的封装等。 data
: 数据层,网络数据、数据库中数据处理层。 domin
: 这层应该是纯 Java 代码,从 data
层出来的数据要经过 domin
转换一下,UI层 app
引用的实体都是 domin
层的。用这种方法来隔离网络和数据库数据变化对代码的影响。 app
: 应该叫 presentation
表现层,觉得这名字太长还是 app
看着舒服~ 这层就是正常的 Android 代码。
这里对 Clean architecture
做了一定的修改,在实践中感觉这样分层开发更顺手。 具体的架构解析及每一层具体该怎么写请关注后面的文章,以后都会详细讲解。
重回刚才的问题,为什么要抽取依赖统一管理?
有四个 module
就有四个 build.gradle
,并且依赖很多都是重复的,分开写在四个不同的文件不利于后期维护升级。 想想如果要更改某个依赖的版本,得打开四个文件挨个改,多麻烦。 所以将可变的依赖抽离出来统一管理是很有必要的。
下面就是具体的操作方法。 把大象装进冰箱需要几步?
三步走:
本项目中在与 app
, data
同级的根目录下创建了文件夹 buildsystem
,然后在这个文件夹下创建文件 dependences.gradle
。目录结构如下图:
dependences.gradle
代码:
ext {
//Android
androidBuildToolsVersion = <span class="hljs-string">"27.0.3"</span>
androidM<span class="hljs-keyword">in</span>SdkVersion = 18
androidTargetSdkVersion = 27
androidCompileSdkVersion = 27
//Libraries
recyclerViewVersion = <span class="hljs-string">"27.0.2"</span>
rxjava2Version = <span class="hljs-string">"2.1.8"</span>
rxandroidVersion = <span class="hljs-string">"2.0.1"</span>
daggerVersion = <span class="hljs-string">"2.14.1"</span>
glideVersion = <span class="hljs-string">"4.5.0"</span>
butterKnifeVersion = <span class="hljs-string">"8.8.1"</span>
bannerVersion = <span class="hljs-string">"1.4.10"</span>
loggerVersion = <span class="hljs-string">"2.1.1"</span>
baseRecyclerViewAdapterHelperVersion = <span class="hljs-string">"2.9.30"</span>
dbflowVersion = <span class="hljs-string">"4.2.4"</span>
app = [
recyclerView : <span class="hljs-string">"com.android.support:recyclerview-v7:<span class="hljs-variable">${recyclerViewVersion}</span>"</span>,
rxjava : <span class="hljs-string">"io.reactivex.rxjava2:rxjava:<span class="hljs-variable">${rxjava2Version}</span>"</span>,
rxandroid : <span class="hljs-string">"io.reactivex.rxjava2:rxandroid:<span class="hljs-variable">${rxandroidVersion}</span>"</span>,
dagger : <span class="hljs-string">"com.google.dagger:dagger:<span class="hljs-variable">${daggerVersion}</span>"</span>,
daggerCompiler : <span class="hljs-string">"com.google.dagger:dagger-compiler:<span class="hljs-variable">${daggerVersion}</span>"</span>,
glide : <span class="hljs-string">"com.github.bumptech.glide:glide:<span class="hljs-variable">${glideVersion}</span>"</span>,
glideCompiler : <span class="hljs-string">"com.github.bumptech.glide:compiler:<span class="hljs-variable">${glideVersion}</span>"</span>,
buterKnife : <span class="hljs-string">"com.jakewharton:butterknife:<span class="hljs-variable">${butterKnifeVersion}</span>"</span>,
butterKnifeCompiler : <span class="hljs-string">"com.jakewharton:butterknife-compiler:<span class="hljs-variable">${butterKnifeVersion}</span>"</span>,
banner : <span class="hljs-string">"com.youth.banner:banner:<span class="hljs-variable">${bannerVersion}</span>"</span>,
logger : <span class="hljs-string">"com.orhanobut:logger:<span class="hljs-variable">${loggerVersion}</span>"</span>,
baseRecyclerViewAdapterHelper: <span class="hljs-string">"com.github.CymChad:BaseRecyclerViewAdapterHelper:<span class="hljs-variable">${baseRecyclerViewAdapterHelperVersion}</span>"</span>,
dbflowProcessor : <span class="hljs-string">"com.github.Raizlabs.DBFlow:dbflow-processor:<span class="hljs-variable">${dbflowVersion}</span>"</span>,
dbflowCore : <span class="hljs-string">"com.github.Raizlabs.DBFlow:dbflow-core:<span class="hljs-variable">${dbflowVersion}</span>"</span>,
dbflow : <span class="hljs-string">"com.github.Raizlabs.DBFlow:dbflow:<span class="hljs-variable">${dbflowVersion}</span>"</span>,
dbflowRx2 : <span class="hljs-string">"com.github.Raizlabs.DBFlow:dbflow-rx2:<span class="hljs-variable">${dbflowVersion}</span>"</span>,
]
}
版本号和具体依赖地址也分开了,更加便于管理。 其中除了依赖的地址,所有的变量名都是随便取的。app
对应于项目module app
里的依赖,当然还有 data
,domin
,common
三个 module 的依赖,声明方式跟 app
一样,只是我还没用到所以没写。
在项目的 build.gradle
第一行加上这行代码: apply from: "buildsystem/dependences.gradle"
声明之后即可在各个 module
中的 build.gradle
中愉快的引用啦。
打开 app
下的 build.gradle
,在需要用到的地方先声明一个变量:
def appDependence = rootProject.ext.app
rootProject 是什么意思我还不太明白,猜测应该是取到项目的根目录。 还记得 dependences.gradle
文件最外层是 ext
节点吗? rootProject.ext
相当于取到了我们提取文件的根节点,rootProject.ext.app
即取到了 app
节点声明的数组。然后再将它赋值给 appDependence
变量。
接下来就可以放心使用啦
implementation appDependence.recyclerView
implementation appDependence.rxjava
贴出 app/build.gradle
代码:
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.androidCompileSdkVersion
buildToolsVersion rootProject.ext.androidBuildToolsVersion
defaultConfig {
applicationId "com.cachecats.meituan"
minSdkVersion rootProject.ext.androidMinSdkVersion
targetSdkVersion rootProject.ext.androidTargetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError <span class="hljs-literal">false</span>
}
//支持Java8特性
compileOptions {
<span class="hljs-built_in">source</span>Compatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
def appDependence = rootProject.ext.app
implementation project(<span class="hljs-string">':common'</span>)
implementation project(<span class="hljs-string">':data'</span>)
implementation project(<span class="hljs-string">':domin'</span>)
implementation fileTree(include: [<span class="hljs-string">'*.jar'</span>], dir: <span class="hljs-string">'libs'</span>)
implementation <span class="hljs-string">'com.android.support:appcompat-v7:27.0.2'</span>
implementation <span class="hljs-string">'com.android.support.constraint:constraint-layout:1.0.2'</span>
<span class="hljs-built_in">test</span>Implementation <span class="hljs-string">'junit:junit:4.12'</span>
androidTestImplementation <span class="hljs-string">'com.android.support.test:runner:1.0.1'</span>
androidTestImplementation <span class="hljs-string">'com.android.support.test.espresso:espresso-core:3.0.1'</span>
//denpendence
implementation appDependence.recyclerView
implementation appDependence.rxjava
implementation appDependence.rxandroid
implementation appDependence.dagger
annotationProcessor appDependence.daggerCompiler
implementation appDependence.glide
annotationProcessor appDependence.glideCompiler
implementation appDependence.buterKnife
annotationProcessor appDependence.butterKnifeCompiler
implementation appDependence.banner
implementation appDependence.logger
implementation appDependence.baseRecyclerViewAdapterHelper
implementation appDependence.dbflowCore
implementation appDependence.dbflowRx2
implementation appDependence.dbflow
annotationProcessor appDependence.dbflowProcessor
}
好啦,以上就是如何统一管理 Android 项目的 Gradle 依赖。 请忽略配图的分辨率和本地项目地址不一样,这篇文章是在三台电脑上完成的……
整个项目的源码都在 Github 上,可以随时查看下载。 源码地址:https://github.com/cachecats/LikeMeiTuan 注:由于项目会一直更新,后期可能会对之前的代码进行重构。如发现源码中代码跟文章中不一致,以源码为准。重构之后我会尽量及时修改博客中的相关内容,与源码保持一致。