美文网首页Android收藏集Android架构设计
Android 架构四:组件化架构实战

Android 架构四:组件化架构实战

作者: IT前沿技术分享 | 来源:发表于2019-04-21 11:12 被阅读306次

    Android 架构系列:
    Android 架构一:Android 架构浅析
    Android 架构二:纵向横向结合构建项目
    Android 架构三:组件化思想
    Android 架构四:组件化架构实战
    Android 架构五:MVVM+Data Binding构建项目
    ……


    一、前言,目前项目架构的困境

    承接上一文,我们开始组件化的实战。

    由于以前的员工对项目的整体规划不足,采取了单工程的方式搭建架构,随着时间的发展,项目冗余功能和代码增多,让app的运行bug频出以及维护成本和维护难度的增加。

    记得在14年的时候做过一次基于Eclipse的项目的结构优化,主要是分为是三个工程:

    Library: 基本库工程
    后台sdk:服务端SDK工程
    主工程: 客户端展示工程

    依赖关系图

    服务端SDK与客户端分开进程,后台sdk依赖Library,主工程依赖后台SDK,这样一个粗略的组件化调整,使得项目维护与管理成本减低了。

    两三年过去了,现在的项目还在用着那套框架,随着APP越来越庞大、开发成员越来越多,并且存在多个业务并发进行的情况,这个结构也越来越不适应了,越来越难维护了,于是下定决心再一次重构,搭建组件化项目框架。

    二、解决办法,组件化架构

    什么是组件化

    组件化是指解耦复杂系统时将多个功能模块拆分、重组的过程,它是一种高效的处理复杂应用系统,更好的明确功能模块作用的方式,分离组件边界和责任,便于独立升级和维护。

    大家都知道现在组件化很火,几乎每家公司都在的使用。为什么他们都要抢着去搭建组件化架构,个人感觉主要是因为它有以下优点:

    • 1、提高了代码的复用度、降低耦合度;
    • 2、实现功能的复用;
    • 3、业务隔离,跨团队开发代码控制和版本风险控制的实现
    • 4、模块化对代码的封装性、合理性都有一定的要求,提升开发同学的设计能力。

    它有这么多的优点,并且都一一击中了我们之前项目架构的痛点,我们有不用的道理么?

    三、如何搭建组件化架构

    在我们开始按照组件化的架构去重构我们的项目之前,我们先要了解如何利用IDE去搭建组件化架构。

    现在Android官方在强推Android Studio,Eclipse已经被逐步弃用,那么我们也紧跟步伐,基于Android Studio搭建组件化。

    这一次的组件化架构是基于之前粗略的组件化方式,作出大量的优化调整,然后利用子工程与壳工程互相配合实现。

    实现目标结构如下:

    壳工程:单个,项目骨架配置相关
    组件工程:多个,多个业务并存且互相独立。
    库工程:多个,基础库、工具库、数据库、第三方框架库、网络库……

    组件化的结构已经订好,那么我们就可以着手去搭建了。

    1、新建项目

    如果直接在之前的项目整理,可想而知,那绝对是个灾难,我们的计划是现在新项目上搭建好组件化架构,再把旧项目拆分重整到新项目里来。

    打开Android Studio,选择 Start a new Android Studio project

    newproject
    后面选择一个空白的,然后下一步输入项目名MyModularization及相关信息,点击OK就可以了。
    此时,Android Studio已经为我们添加了默认的Module: app,即我们的壳工程,它是一个app的骨架性配置,一些库的初始化之类的,没有什么代码实现。

    2、为MyModularization添加组件

    壳工程建立完毕,接下来通过添加Module的方式添加库组件和业务组件。

    2.1、为MyModularization添加Library

    右键点击MyModularization,选择new,再选择module

    Jietu20190418-100611.jpg
    在新窗口上选择Android Library,next,再输入相关信息即可
    AndroidLibrary.jpg
    2.2、为MyModularization添加业务组件

    跟1.2差不多,只是在新窗口上选择的不是Android Library,而是Phone & Tablet Module,这样,我们为项目添加了两种类型的组件LibraryModule,一般组件的类型就是这两种。

    3、两种组件的区别

    这两种组件(其实就是eclipse下的子工程)之间有什么区别呢,我们打开各自的build.gradle,看一下第一行
    lib_base:

    apply plugin: 'com.android.library'
    

    module_login:

    apply plugin: 'com.android.application'
    

    这里,我们可以看出,库组件只仅仅是个库,不能单独运行,而业务组件则是application,能单独运行。

    项目及组件添加完成后,我们还要做一些配置。

    4、库模块的配置

    如果,我们在添加的时候,已经选择了Library,IDE基本上已经帮我们配置完成,但是如果需要把一个非Library类型的组件修改为业务组件,则需要如下操作

    4.1、配置apply plugin

    build.gradle中的apply plugin: ‘com.android.application’修改成apply plugin: ‘com.android.library’

    4.2、调整manifest

    manifest中的代码作如下修改

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="yb.demo.modularization.lib_base" />
    

    5、业务组件中的配置

    因为组件化的其中一个优势,组件需要具备单独开发调试测试,故,作为整体的一部分时,组件是个Library,而开发过程中,组件是个Application,故配置如下:

    5.1、添加调试开关

    projectbuild.gradle中添加是否Application的开关

    ext {
        isModule = true;
    }
    
    5.2、配置plugin类型

    build.gradle的顶部添加如下代码,读取开关,做相应的配置

    if(rootProject.ext.isModule.toBoolean()){
        apply plugin: 'com.android.application'
    } else {
        apply plugin: 'com.android.library'
    }
    
    5.3、添加applicationId

    build.gradle添加applicationId

    android {
        …………
    
        defaultConfig {
            if(rootProject.ext.isModule.toBoolean()){
                applicationId "com.example.login"
            }
    
        …………
    }
    
    5.4、添加两种AndroidManifest.xml

    在Module中添加一个/src/main/module的文件夹,并在module创建AndroidManifest.xml*配置文件,用来在模块开发时能够单独打包,配置如下:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.login">
    
        <application
            android:name=".debug.MyApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme" >
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name"
                android:theme="@style/AppTheme.NoActionBar">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            …………
    </manifest>
    

    在module包下添加文件/src/main/java/包下/debug/**MyApplication.java **,做一些调试的开发相关的实现。

    而作为 Library 的配置文件 /src/main/AndroidManifest.xml的配置调整如下

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.login">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.example.login.MainActivity"
                android:label="@string/app_name"
                android:theme="@style/AppTheme.NoActionBar">
            </activity>
            …………
    </manifest>
    
    5.5、配置选择AndroidManifest

    前面一步已经让module拥有了两个配置文件,接下来就是根据前面添加的开关,判断使用哪个配置文件。
    还是在build.gradle文件作出以下调整:

    
    android {
    
            …………
    
        sourceSets {
            …………
    
            main {
                if (rootProject.ext.isModule.toBoolean()) {
                    manifest.srcFile 'src/main/module/AndroidManifest.xml'
                } else {
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                    //集成开发模式下排除debug文件夹中的所有Java文件
                    java {
                        exclude 'debug/**'
                    }
                }
            }
    
            
            …………
        }
    
        …………
    }
    
    5.6、依赖库工程

    业务组件需要依赖对应的库工程才能,进行相关功能的实现。
    在业务的build.gradle文件做如下配置:

    dependencies {
        ……
    
        api project(':lib_base')
    }
    
    5.7、让业务工程具备独立调试的能力

    在业务的build.gradle文件做如下配置:

    dependencies {
        ……
    
        if(rootProject.ext.isModule.toBoolean()){
            // andorid text
            testImplementation 'junit:junit:4.12'
            androidTestImplementation 'com.android.support.test:runner:1.0.2'
            androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
        }
    
        api project(':lib_base')
    }
    

    6、壳工程依赖库工程及业务工程

    appbuild.gradle文件做如下配置:

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    
    //旧版本Android Studio配置关键字
    //    compile project(':module_login');
    //    compile project(':lib_base');
        api project(':module_login');
        api project(':lib_base');
    }
    

    ok,这样我们组件化基本架构就搭建完毕了,在壳工程与业务工程、库工程关联完毕后,就可以作为一个项目来进行开发了。

    当然,这里只是举例了lib_basemodule_login的相关配置,其他的子工程也无非这两种类型的其中一种,配置都是一样的,他们统统做相应的配置即可。

    四、利用ARouter降耦合

    进过上面的配置,我们的组件化基本架构已经完成,这里还有个问题存在,就是每个子模块之间不能直接调用,那么我们怎么进行模块之间的跳转与数据交流呢。
    首先想到的解决的办法有两个,隐式跳转和反射,但是,这两种方式一种实现维护麻烦,一种对性能会有影响,都不是理想的解决办法,此时类似ARouter和ActivityRouter等的路由框架就派上用场了。

    我们选择的是阿里的ARouter路由框架,,我们先来简单了解一下ARouter的原理

    路由框架会扫描所有添加@Route注解的Activity类,然后将Route注解中的path地址和Activity.class文件建立映射关系并且保存到它自己生成的java文件中,以实现跳转。

    详解ARouter路由框架原理。(貌似也还没有写,加下文提到的“纵向横向重构项目”,后面会抽时间完成)
    接下来,我们就可以把ARouter运用到我们的组件化中了。

    1、配置引用ARouter

    我们一般把公用第三方框架放在lib_base中,故在lib_basebuild.gradle文件做如下配置:

    dependencies {
        ………………
    
        // ARouter
        // 替换成最新版本, 需要注意的是api
        // 要与compiler匹配使用,均使用最新版可以保证兼容
        api 'com.alibaba:arouter-api:1.4.1'
        annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
    
    }
    

    2、子工程引入路由器

    在需要对外提供跳转的子工程中添加路由器,在对应的module的build.gradle文件做如下配置:

    if(rootProject.ext.isModule.toBoolean()){
        apply plugin: 'com.android.application'
    } else {
        apply plugin: 'com.android.library'
    }
    
    android {
        ………………
    
        defaultConfig {
            ………………
    
            // ARouter
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName()]
                }
            }
    
        }
    
        ………………
    }
    
    dependencies {
        implementation fileTree(include: ['*.jar'], dir: 'libs')
    
        if(rootProject.ext.isModule.toBoolean()){
            // andorid text
            testImplementation 'junit:junit:4.12'
            androidTestImplementation 'com.android.support.test:runner:1.0.2'
            androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
        }
    
        // ARouter
        annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
    
        api project(':lib_base')
    }
    
    

    3、添加注解

    在需要夸module跳转的activity中添加注解:

    // 在支持路由的页面上添加注解(必选)
    // 这里的路径需要注意的是至少需要有两级,/xx/xx
    @Route(path = "/com/example/login/MainActivity")
    public class MainActivity extends AppCompatActivity
            implements NavigationView.OnNavigationItemSelectedListener {
        ………………
    }
    

    4、使用路由器夸module跳转

    注解添加后,我们就可以通过path实现夸module跳转了。在需要startActivity的地方做调整:

        //弃用    
        private void showActivity(Class<?> cls){
            Intent show = new Intent(this, cls);
            startActivity(show);
        }
    
        private void showActivity(String path){
            // 应用内简单的跳转(通过URL跳转在'进阶用法'中),还有带参跳转,以后在单独见ARouter的时候一起讲。
            ARouter.getInstance().build(path).navigation();
        }
    

    5、Kotlin项目中的配置方式

    // 可以参考 module-kotlin 模块中的写法
    apply plugin: 'kotlin-kapt'
    
    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }
    
    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        kapt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
    

    OK,这样就可以把ARouter运用到我们的架构中了,为架构降耦作贡献。

    五、组件化思维重构项目

    以上,我们就搭起了组件化的架构,接下来才是头疼的事情。

    重构的关键是要有组件化的思维,我们首先要做的是,理清冗余杂乱重复的功能模块、工具具模块以及纷繁错乱的业务。

    由于篇幅的原因,我们这里只讲搭建组件化架构,不讲重构,如想了解我们是怎么重构的,另见Android组件化二:纵向横向重构项目, 貌似还没写!!;

    既然不讲过程,那么就直接来结果吧

    组件的划分:


    组件化结构.jpg

    组件化结构:


    组件化结构.jpg

    然后,既然讨论清楚,也就是设计完毕啦,接下来就可以进入-炼狱了,你懂的。

    六、结语

    虽然重构的过程是痛苦的,甚至有时候会觉得生不如死,但是,我们一定要坚持下来,因为,坚持到最后,项目组件化起来了,大大降低了项目维护的成本,各种爽各种嗨。
    本文详细的介绍了,如何搭建一个简单易懂的组件化架构,如果你们的项目还没有接入组件化架构,不妨参考一下。
    能力有限,如有哪里描述不当或者不清楚的地方,望各位大大指出,谢谢。

    相关文章

      网友评论

        本文标题:Android 架构四:组件化架构实战

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