Android组件化开发之接口API化

2021-09-15  本文已影响0人  风月寒

在组件化中,为了避免相同层级的模块之间交叉依赖,这个时候就可以把模块之间相互调用的方法抽象成接口下沉到公共模块,但是这也导致了一个问题,我们对公共模块进行依赖的时候,可能只使用了其中的一两个接口,那这样的话既导致公共模块的臃肿,也增加了编译的时间。所以微信团队在《微信Android模块化架构重构实践》给出了API化这个方案。

思路

1、将工程里想要暴露出去的接口类是Java文件,则将后缀名.Java改成.api,如果是kt文件,则将后缀名.kt改成.kapi。

2、然后利用脚本自动生成一个xxx-api模块。然后供其他的模块进行调用。调用的方式可以根据我前一篇文章Android组件化开发之SPI

脚本代码如下:

gradle.projectsLoaded {
    // 自动为module引入生成的module-api
    gradle.rootProject.allprojects.forEach { Project p ->
        p.afterEvaluate {
            def apiProject = gradle.rootProject.allprojects.find {
                it.name.endsWith("${p.name}-api")
            }
            if (apiProject != null) {
                p.dependencies.add("api", apiProject)
            }
        }
    }
}
//自定义include
ext.includeWithApi = { String moduleName ->
    include(moduleName)
    String originDir = project(moduleName).projectDir
    String targetDir = "${originDir}-api"

    //新模块的路径
    def sdkName = "${project(moduleName).name}-api"

    // 每次编译删除之前的文件
    deleteDir(targetDir)
    //复制.api文件到新的路径
    copy() {
        from originDir
        into targetDir
        exclude '**/build/'
        exclude '**/res/'
        include '**/*.api'
        include '**/*.kapi'
        include 'api.gradle'
    }

    def build = new File(targetDir + "/api.gradle")
    if (build.exists()) {
        build.renameTo(new File(targetDir + "/build.gradle"))
    }

    // 重命名.api文件,生成正常的.java文件
    renameApiFiles(targetDir, '.api', '.java')
    renameApiFiles(targetDir, '.kapi', '.kt')

    //删除空文件夹
    deleteEmptyDir(new File(targetDir))
    //正常加载新的模块
    include /*prefixName +*/ "$sdkName"
}


private void deleteEmptyDir(File dir) {
    if (dir.isDirectory()) {
        File[] fs = dir.listFiles();
        if (fs != null && fs.length > 0) {
            for (int i = 0; i < fs.length; i++) {
                File tmpFile = fs[i];
                if (tmpFile.isDirectory()) {
                    deleteEmptyDir(tmpFile);
                }
                if (tmpFile.isDirectory() && tmpFile.listFiles().length <= 0) {
                    tmpFile.delete()
                }
            }
        }
        if (dir.isDirectory() && dir.listFiles().length == 0) {
            dir.delete()
        }
    }
}

private void deleteDir(String targetDir) {
    FileTree targetFiles = fileTree(targetDir)
    targetFiles.exclude "*.iml"
    targetFiles.each { File file ->
        file.delete()
    }
}


private def renameApiFiles(root_dir, String suffix, String replace) {
    FileTree files = fileTree(root_dir).include("**/*$suffix")
    files.each {
        File file ->
            file.renameTo(new File(file.absolutePath.replace(suffix, replace)))
    }
}
上一篇下一篇

猜你喜欢

热点阅读