Android面试知识Android知识手机移动程序开发

android模块化简单教程

2017-06-28  本文已影响1295人  低情商的大仙

当项目大到一定程度后,公司各个模块的业务相互耦合,维护的时候非常困难,另外项目大到一定程度后,编译速度也是个坑爹的东西,所以这个时候模块化就显得很有必要了。最近公司一直在推进这方面的工作,于是我也从gayhub上fork了一个项目动手实践起来,下面做个简单的记录。

先贴代码,对着代码看更直观:示例代码

1.模块划分

模块化的第一步就是模块划分要明确,否则所谓的模块化无从谈起。由于本项目直接fork自 https://github.com/BaronZ88/ModularizationProject ,所以直接偷了他的模块划分图来:

模块图
可以很明显的看到整个模块分为三层,基础组件层,基础业务层,业务层。最底下一层包含一些第三方开源库和公司自己开发的各种底层库,在这一层中基本上通过gradle引入的第三方框架都在这里配置;第二层是基础业务库,所谓的基础业务库就是有很多业务都可能涉及到这些的,比如一些公用的vo,比如登录业务,比如支付系统;最高一层就是我们真正的模块化的各种业务,这一层的任何一个不同模块都应该可以单独作为一个app跑起来,每次开发时应该只需要运行某一个模块,从而避免影响其它业务。在我们的示例代码中,结构就是这样的:

其中App模块就是我们的主模块,运行这个模块保证所有模块都会被当做module引入,然后其它以Module结尾的都可以单独运行起来。另外CommonBusiness和CoreModel是基础业务层的模块,OpenSourceLibrary是最底下一层基础组件层的module。
有了这些基础,模块化才能继续进行下去

2.配置运行不同的模块

(1)区分两种状态

首先要明确一点,对任意一个业务module来说,它都有两种状态,一种是运行App模块时的module状态,单纯提供依赖,一种是模块单独运行时的可运行状态。
为了区分这两种状态,我们在gradle.properties文件中添加了一个变量isBuildModule,当为true的时候,各个业务模块能够单独运行,当为false时,每个业务module无法单独跑起来只能作为module引入,将整个应用跑起来,此时只有App模块能运行。

(2)配置两种状态下的gradle文件

一个module是否可以单独运行,是由它的gradle文件中的配置决定的,该module如果只是一个library,通常我们这样写:
apply plugin: 'com.android.library'
但如果要让该module能单独跑起来我们要这么写:
apply plugin: 'com.android.application'
综合一下,结合isBuildModule变量,最终我们这么处理:

if (isBuildModule.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

这样,我们就能够通过修改isBuildModule来配置是否单独运行模块。

(3)提供两套AndroidManifest.xml文件

由于一个module要想单独跑起来,那么我们必须要指定启动的Activity,但是当isBuildModule为false时又不需要,所以我们要准备两套Manifest文件。以NewHouseModule为例:



Manifest文件分为debug模式和release模式,debug模式就是该模块可以单独运行的模式。然后在该module的gradle文件中配置下:

  sourceSets {
        main {
            if (isBuildModule.toBoolean()) {
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/release/AndroidManifest.xml'
            }
        }
    }

这里分别看下两种文件的区别:
debug:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.baronzhang.android.newhouse">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/new_house_ic_launcher"
        android:label="@string/new_house_app_name"
        android:supportsRtl="true"
        android:theme="@style/NewHouseAppTheme">
        <activity
            android:name="com.baronzhang.android.newhouse.NewHouseMainActivity"
            android:label="@string/new_house_label_home_page">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

release:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.baronzhang.android.newhouse">

    <application
        android:allowBackup="true"
        android:supportsRtl="true">
        <activity
            android:name="com.baronzhang.android.newhouse.NewHouseMainActivity"
            tools:replace="label"
            android:label="@string/new_house_label_home_page">
        </activity>

    </application>

</manif

这里差距主要是是否配置了启动Activity。

(4)配置依赖关系

经过上面三部的配置,按道理可以通过修改isBuildModule变量来配置是否让某个模块单独运行了,然后事实不是这样,当isBuildModule为true时,这个时候运行App模块会报错,我们需要修改下App模块下的gradle文件:

  if (isBuildModule.toBoolean()) {
        compile project(':CoreModel')
        compile project(':CommonBusiness')
    } else {
        compile project(':InstantMessagingModule')
        compile project(':NewHouseModule')
        compile project(':SecondHouseModule')
    }

当运行的是某个模块是,每一个业务module都是一种application,而不是library,是不能以compile project的方式引入的,所以要排除掉,但也同时排除了这些module依赖的一些基础业务库,所以我们要引入进来。这样,配置每个模块单独运行就完成了。

3.配置路由跳转

由于不同的业务相互解耦的非常彻底,然后有些时候必然会出现一个模块要跳往另一个模块,这种时候,系统自带的跳转已经不行了,因为该模块中没有另一个模块的Activity,这里可以考虑通过Scheme跳转,但一来配置麻烦,二来还有安全风险,所以不推荐。这个时候,Android页面路由就该上场了。
原作者自己撸了一个页面路由框架,我等渣渣只能膜拜,然后自己去github上找了下,最终选定了阿里巴巴开源的ARouter,配置简单,上手简单,使用简单。该框架的详细使用教程看这里:https://github.com/alibaba/ARouter 。这一步没有难度,照着文档来就行了,注意一点,凡是使用ARouter的模块,都要在build.gradle文件中加入

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

这里更推荐的是将 compile 'com.alibaba:arouter-api:x.x.x' 放到OpenSourceLibrary模块中去,每个模块只需要配置annotationProcessor即可。

总结

经过以上操作,最简单的模块化就完成了,后面会继续介绍一些稍微麻烦一些的内容:
Android模块化之登录业务处理
Android模块化之ButterKnife和Dagger2的使用
参考文档:
Android 模块化探索与实践

上一篇下一篇

猜你喜欢

热点阅读