微信公众号:伴职创作
IT类、哲学、散文、叙事情感类、小说…欢迎你来投稿。
Android工程架构一直是老生常谈的事情,如何很好的架构出一个工程,其实是占住了重要的重要。
下面是我自己谈谈,这几年在开发一款APP中经常使用的架构模式:
以基于ARouter为例说明组件化如何构建:
1、实现自定义Application。
/**
* 自定义Application实现相关方法的初始化工作
*
* @author 邹峰立
*/
public class MyApplication extends BaseApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
@Override
public void onCreate() {
super.onCreate();
// 启动服务执行耗时操作
InitializeService.start(this);
}
}
2、实现IntentService冷启动。
/**
* 初始化APP -
*/
public class InitializeService extends IntentService {
private static final String ACTION_INIT_WHEN_APP_CREATE = "cc.ibooker.service.action.INIT";
public InitializeService() {
super("InitializeService");
}
public static void start(Context context) {
Intent intent = new Intent(context, InitializeService.class);
intent.setAction(ACTION_INIT_WHEN_APP_CREATE);
intent.setComponent(new ComponentName("com.xizhi_ai.aixizhi", "cc.ibooker.app.InitializeService"));
context.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_INIT_WHEN_APP_CREATE.equals(action)) {
performInit();
}
}
}
private void performInit() {
// 异常捕获
CrashHandler.getInstance().init(getApplication());
// 初始化第三方库
// 初始化组件
}
}
3、管理版本(build.gradle-工程),例如:
//noinspection GradlePluginVersion
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:' + localGradlePluginVersion
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
// Add the JitPack repository
maven { url "https://jitpack.io" }
// 支持arr包
flatDir {
dirs 'libs'
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
buildToolsVersion = localBuildToolsVersion
compileSdkVersion = 28
minSdkVersion = 16
targetSdkVersion = 28
versionCode = 13
versionName = "2.0.8"
}
4、统一混淆,打包,签名,压缩等(build.gradle-app,proguard-rules.pro),例如:
build.gradle-app:
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "cc.ibook"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
/*ARouter*/
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
signingConfigs {
release {
storeFile
storePassword
keyAlias
keyPassword
v1SigningEnabled true
v2SigningEnabled true
}
debug {
v1SigningEnabled true
v2SigningEnabled true
}
}
getSigningProperties()
buildTypes {
release {
// 不显示Log
buildConfigField("boolean", "LEO_DEBUG", "false")
// 是否可调试-上线之前关闭
// debuggable false
// jniDebuggable false
// 是否zip对齐
zipAlignEnabled true
// 缩减resource文件
shrinkResources true
// 混淆
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// 签名配置
signingConfig signingConfigs.release
}
debug {
// applicationIdSuffix ".debug"
versionNameSuffix ".debug"
buildConfigField("boolean", "LEO_DEBUG", "true")
zipAlignEnabled false
shrinkResources false
minifyEnabled false
debuggable true
jniDebuggable true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
}
//配置签名文件
def getSigningProperties() {
File propFile = file('signing.properties')
if (propFile.exists()) {
Properties props = new Properties()
props.load(new FileInputStream(propFile))
if (props.containsKey('STORE_FILE') &&
props.containsKey('STORE_PASSWORD') &&
props.containsKey('KEY_ALIAS') &&
props.containsKey('KEY_PASSWORD')) {
android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']
} else {
android.buildTypes.release.signingConfig = null
}
} else {
android.buildTypes.release.signingConfig = null
}
}
allprojects {
repositories {
maven { url 'https://jitpack.io' }
jcenter()
}
}
buildscript {
repositories {
jcenter()
}
}
dependencies {
api fileTree(include: ['*.jar'], dir: 'libs')
testImplementation 'junit:junit:4.12'
//noinspection GradleCompatible
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
if (isModule.toBoolean()) {
implementation project(':commonlib')
} else {
implementation project(':melib')
implementation project(':studylib')
implementation project(':mainlib')
implementation project(':photochooselib')
annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
implementation project(':xizhitopiclib')
}
}
5、开关控制(gradle.properties),例如:
# 为自动化出包配置
localBuildToolsVersion = 28.0.3
# 本地Gradle版本 - 一般跟你的AndroidStudio版本号一致
localGradlePluginVersion = 3.2.1
# 是否是组件开发模式,true为是,false为否
isModule = false
# 是否开始NDK
android.useDeprecatedNdk = true
提供APP入口组件,如:
1、进入工程启动页,例如GuideActivity,WelComeActivity,MainActivity等。
…
整个工程都能够进行直接使用的组件,如:
1、基类
2、工具类
3、自定义View
4、jar,.so文件,配置文件等
…
例如:RxJava+Okhttp+Retrofit+Glide+Gson
网络请求框架,图片加载框架,下载器等。
本地数据组件:
1、静态常量,保存:token等
2、SharedPreferences,保存setting信息等
3、SqlLite,保存数据对象,如用户信息等
4、File,保存文件、图像等
…
除了保存数据,还要实现数据得操作类,缓存类。如果要实现跨进程要实现跨进程通信IPC。
包含业务逻辑的组件。
1、可以是SDK。
2、可以是module。
…
如果区分Phone,Pad,Computer的话,可以采用flavorDimensions,sourceSets。
注意:所有业务组件都可以导入公共组件,以便使用公共组件内容。
业务组件build.gradle如何实现案例,以主组件为例:
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
if (isModule.toBoolean()) {
applicationId "cc.ibooker.mainlib"
}
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
/*ARouter*/
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
if (isModule.toBoolean()) {
manifest.srcFile 'src/main/mainlib/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
// 集成开发模式下排除debug文件夹中的所有Java文件
java {
exclude 'debug/**'
}
}
}
}
}
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
//noinspection GradleCompatible
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// 公共组件
api project(':commonlib')
annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
}
为实现一个或多个功能或UI而特定的组件,如:
1、实现特定功能组件。
2、实现特定布局组件。
3、一些特殊逻辑组件。
…
总结:APP的所有控制交给APP空壳,而业务组件间的通讯交给路由,如:ARouter。没有业务组件,可以有自己的common包,数据data包等,自己负责自身的逻辑处理。
Model层:数据层,主要是用来存取数据。
View层:视图层,显示数据。
Controller层:控制层,从视图读取数据,控制用户输入,并向模型发送数据。
Model层:数据层,主要是用来存取数据。
View层:视图层,显示数据。
Presenter层:控制层,从视图读取数据,控制用户输入,并向模型发送数据。
个人理解:V层负责傻瓜式显示数据,P进行一些逻辑判断和数据处理,M层存、取、解析数据。
推荐MVP结构网址:ZMvp
Model层:数据层,主要是用来存取数据。
View层:视图层,显示数据。
VM层:控制层,从视图读取数据,控制用户输入,并向模型发送数据。
总结:这三种结构基本显示,只是控制层的作用域变了,这些模式也是依次进化而形成MVC->MVP->MVVM。
最后推荐我的另一篇文章:
BaseActivity基类设计【Android】