App下载 微信公众号

Android架构设计

技术 · 移动开发 · Android/ 作者【吾非言】/ 发布于2019-11-2/ 212次浏览
2019 11/2 2:41
摘要: 软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。

微信公众号:伴职创作
IT类、哲学、散文、叙事情感类、小说…欢迎你来投稿。

伴职创作

Android工程架构一直是老生常谈的事情,如何很好的架构出一个工程,其实是占住了重要的重要。

下面是我自己谈谈,这几年在开发一款APP中经常使用的架构模式:

组件化

以基于ARouter为例说明组件化如何构建:

一、APP空壳

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')
    }
}

proguard-rules.pro

5、开关控制(gradle.properties),例如:

# 为自动化出包配置
localBuildToolsVersion = 28.0.3

# 本地Gradle版本 - 一般跟你的AndroidStudio版本号一致
localGradlePluginVersion = 3.2.1

# 是否是组件开发模式,true为是,false为否
isModule = false

# 是否开始NDK
android.useDeprecatedNdk = true

二、主组件(MainLib)

提供APP入口组件,如:
1、进入工程启动页,例如GuideActivity,WelComeActivity,MainActivity等。

三、公共组件(CommonLib)

整个工程都能够进行直接使用的组件,如:
1、基类
2、工具类
3、自定义View
4、jar,.so文件,配置文件等

四、数据组件

1、网络组件(NetLib)

例如:RxJava+Okhttp+Retrofit+Glide+Gson
网络请求框架,图片加载框架,下载器等。

2、本地组件(LocalLib)

本地数据组件:
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包等,自己负责自身的逻辑处理。

MVP/MVC/MVVM

一、MVC:Model View Controller

Model层:数据层,主要是用来存取数据。
View层:视图层,显示数据。
Controller层:控制层,从视图读取数据,控制用户输入,并向模型发送数据。

图片描述

二、MVP:Model-View-Presenter

Model层:数据层,主要是用来存取数据。
View层:视图层,显示数据。
Presenter层:控制层,从视图读取数据,控制用户输入,并向模型发送数据。

个人理解:V层负责傻瓜式显示数据,P进行一些逻辑判断和数据处理,M层存、取、解析数据。

图片描述

推荐MVP结构网址:ZMvp

三、MVVM:Model-View-ViewModel

Model层:数据层,主要是用来存取数据。
View层:视图层,显示数据。
VM层:控制层,从视图读取数据,控制用户输入,并向模型发送数据。

图片描述

总结:这三种结构基本显示,只是控制层的作用域变了,这些模式也是依次进化而形成MVC->MVP->MVVM。

最后推荐我的另一篇文章:
BaseActivity基类设计【Android】

感谢您使用伴职平台,如有侵权,请投诉删除!

全部评价

最新
查看更多评论 加载

猜你喜欢

换一批