yunshuipiao / Potato

Read the fucking source code for the Android interview
Apache License 2.0
80 stars 12 forks source link

Android: Multi Module Structure #65

Open yunshuipiao opened 5 years ago

yunshuipiao commented 5 years ago

Android: Multi Module Structure

在笔者多年的安卓开发中,有意识的在思考一个 Android 项目的目录结构,下面是我的分享。

对于一个 Android 项目,我认为至少应该分为 4个模块。工具,基础,业务功能,App模块。

工具模块

请看下图:(一个小小的建议:分别以 library, module 前缀)命名

image

如上图模块中的 module_swutils 就是整个项目最常用的工具类,应该被所有项目依赖。其内容应该与项目业务无关,包括工具类,常量,等等。比如 日志模块的封装,图片加载模块的封装。并使用 ContentProvider 进行自动注册。

object SwUtils {
    lateinit var application: Application
    fun init(application: Application) {
        SwUtils.application = application
        var isDebug = (application.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0
    }
}

比如上面的 SwUtils, 保存全局的 Application 供本模块使用。另外建议每个模块都有唯一的 application 作为 context 使用,不用使用其他模块的。或者在每个模块用一个变量保存工具模块的 application,作为本模块使用。

class UtilContentProvider : ContentProvider() {
    override fun query(
        uri: Uri,
        projection: Array<String>?,
        selection: String?,
        selectionArgs: Array<String>?,
        sortOrder: String?
    ): Cursor? {
        return null
    }

    override fun onCreate(): Boolean {
        SwUtils.init(context as Application)
        return true
    }

    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int {
        return 0
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
        return 0
    }

    override fun getType(uri: Uri): String? {
        return null
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        return null
    }
}

上面使用 provider 对模块进行自动注册,这种用法很多,就不展开讲了。

上面就是工具模块的整体结构:纯工具,与业务无关

基础模块

module_base 模块,我理解为基础模块。其内容包括对 Activity,Fragment,View 的基础封装, BaseActivity 之类的。另外还有一些被具体业务使用到的自定义view。此模块不建议存放xml资源,比如 string.xml (多语言)。这些资源应该放在具体用到的业务模块下。

api project(":module_swutils")

通过 api 的方式以来 工具模块,是的在其他模块也能使用。

业务模块

上面的 module_fun1, module_fun2, module_wechat 都是业务模块,具体实现项目的业务功能。

在实现的过程中,遇到共有的部分,根据是否与业务有关,往下放入 base 或者 utils 模块。

业务模块之间不相互依赖,组件间跳转可以使用 Arouter。

业务模块依赖 base 模块。

App功能

App 作为项目的 Project,在理想的情况下应该不包含任何的业务逻辑实现,单纯只作为项目的启动模块。

另外,除了这四个模块,可能由于工具模块或者base模块过大, 可以分一个 module_third 三方模块,用于存放对开源模块的一些封装。

对于公司有多个项目的情况:

由于 utils 是与业务完全无关的,因此可以维护该模块,并上传 maven 作为内部的共有模块进行使用。

总结

项目大致分为四个模块:

utils:工具模块,完全与业务无关,纯函数 (命名建议:library_utils)

base:基础模块,常用 UI 的封装,与业务有关的函数和常量,依赖上层 (命名建议:与业务有关 library_base)

funx:具体业务模块,依赖 base。( 命名建议:module_funx )

App;壳工程,尽量不实现业务,只负责启动项目。(命名建议:app)

有好的想法可以补充,欢迎交流。