Rubik:基于 Kotlin 的 Android 组件化开发框架开源!


前言

    随着Android平台的飞速发展,许多老牌App,都发展成了所谓的“超级应用”,不但功能模块众多、代码量巨大,团队规模更是扩大到了几十人甚至上百人的规模。一线大厂的旗舰应用,甚至可能涉及到多个部门的协同开发。     在这个过程里,必然的产生了一些“代码复用”和“协同效率”方面的问题。所以,组件化开发逐渐被各个大厂提上了日程。如今,移动端开发除了要解决“代码”方面的问题,也需要关注“工程”方面的问题。     2022年,百度网盘App迎来了10周年,在这10年的发展过程中,我们也遇到过各种各样的的“工程”问题,为了解决这些问题,我们引入了组件化开发,而Rubik就是在这个过程中诞生的。  

关于Rubik

    Rubik由百度网盘团队出品,从2019年开始建设,至今已经迭代了两个大版本,并在多款线上产品中得到应用。     Rubik是一套解决Android平台组件化的综合框架,也就是说,Rubik在帮助我们实现模块解耦的同时,还能能够提供一些组件管理能力。Rubik所提供的模块解耦能力是一种基于“函数路由”的组件间低耦合通讯方案。组件管理能力能够帮助我们实现组件的版本控制、maven发布、aar/jar与源码之间的切换等能力,Rubik还可以通过配置文件,更简便的把现有的组件,组合成不同的APK。 Rubik框架的工程结构       换而言之,Rubik专注于解决Android应用开发过程中的组件化问题。但是,Rubik作为一个完全由Kotlin语言实现的开源框架,即使你没有组件化开发方面的需求,也非常欢迎关注Rubik的技术实现,欢迎阅读Rubik的代码,因为:     首先,Rubik完全采用kotlin开发,并且大量应用了Kotlin的函数式编程、DSL等特性,非常适合正在学习Kotlin的小伙伴交流学习;     另外,在Rubik的实现过程中,也应用到了Kotlin代码自动生成方面的技术。几乎尝试了目前全部Kotlin代码自动生成的相关方案,也用到了Tranform这样的传统的字节码修改技术。     最后,作为一个贯穿于Android编译过程的工具链类项目,Rubik中有大量的,关于Gradle插件方面的实践,也封装了大量的Gradle方面的工具类。非常适合想要开发Gradle插件的小伙伴参考和借鉴。最重要的是,这一切都是基于Kotlin的。  

关于组件化

    关于组件化开发,有很多不同的定义。在这里,定义并不重要,我们更应该关心,对于客户端开发而言,组件化开发所能解决的最核心的问题是什么。我们认为,组件化开发的核心,在于两点:
  • 隔离:让业务组件之间保持相对的独立性
  • 复用:复用业务组件形成可运行软件
 

怎样才算彻底的组件隔离?

让业务组件之间保持独立性,通常可以与代码层面上的“解耦”划上等号,如果两个业务的代码混杂在一起,缺乏对边界的定义,肯定是代码隔离不彻底的表现。 代码隔离不彻底的情况   另外,对于组件化来说,业务隔离的标准还要更苛刻一些,当两个模块,在业务上的关联并不强时,如果存在直接的代码调用,也要视作代码隔离不彻底。由于编译顺序的关系,在Android平台,模块之间是无法建立双向的代码依赖的,这显然与组件化的理念有出入,我们希望组件之间是平等、独立的,应该可以自由的在任何组件之间建立松耦合的依赖关系。像这种基于代码调用的单向依赖,本质上一种“剪不断”的“从属关系”。 代码隔离不彻底的情况

 

所以,在组件化开发中,组件之间应该保持没有代码耦合,在需要互相通信时,使用一种通过接口,间接的依赖的通信方式。   间接的依赖

 

    在实际的组件化开发过程中,隔离往往是最难以实际操作的,无论是面对难以维护的历史代码,还是在前期规划不足的新业务。但是,一旦清晰的划分出两个组件间的边界,把彼此的代码隔离开,就会带来一系列的工程方面的好处:
  • 明确开发人员的职责:由于对一个模块的修改不会直接影响另一个模块,所以负责开发不同模块的开发人员,只需要对约定好的接口负责,不需要关心其他组件的具体实现。
  • 降低测试成本:同样的,对于测试人员而言,如果能够保证对一个组件的修改,只影响组件本身和组件的接口,那么对于没有被修改过的组件,就没有回归测试的必要了。
  • 提升编译速度:在实际开发中,可以让大部分组件提前编译成二进制,只让少数经常变更的组件保持源码状态。
  • 故障隔离:当一个组件出现故障,能够做到不影响其他组件的正常运行。
      对于组件的隔离,可以总结成一句话:隔离代码不是目的,隔离变化才是最重要的!     除此之外,隔离也是对组件进行复用的前提,只有隔离了一个业务组件对外部的全部隐式的影响,才能保证这个组件在被其他场景复用时是安全、可靠、无副作用的。  

组件级别的复用应该做到什么程度?

    组件级别的复用,指的是在不同应用程序之间,复用已有的业务组件。这往往都是为了快速搭建新项目,并且最大限度的保证新老项目的代码的一致性,从而降低代码的维护成本。所以,组件化开发框架,应该能够做到对现有的组件进行储备,并且在新项目启动时,通过简单的配置,对已有的组件进行筛选,快速的生成新的应用程序。   组件的筛选复用       在实际开发中,有可能会遇到同一个组件,给不同的应用复用时,存在一些功能差异的情况。所以,组件化框架也必须能够做到将同一套代码,差异化的编译成在功能上略有差异的组件变体,以便在不同需求下复用。 组件的变体复用  

Rubik在组件化中的作用?

    Rubik由两部分组成,一部分是解决组件间低耦合通信的Rubik Router模块,另一部分是基于Gradle Plugin实现的Rubik工具链,负责解决组件管理和依赖管理方面的问题。  

Rubik Router:基于Kotlin DSL的“函数”路由

    Rubik在依赖倒置与依赖注入的基础上,实现了一套基于Uri的路由通信方式,与一般的页面路由或四大组件路由不同,Rubik Router允许把Uri及参数,导航到组件内部任意的一个公开的Java或Kotlin函数的执行上。Rubik Router的选择以函数而非Android中的四大组件为路由的终点,主要基于三方面考虑:
  • 灵活性:在实际开发中,组件的边界通常不是简单的页面跳转,有可能是Api的调用或数据、实例的获取,相比于传统的页面路由,“函数”路由可以更加轻量级的满足这些需求。
  • 可扩展性:“函数”路由有更低的层次,使用者可以在函数的基础上延伸更多的用法。
  • 一致性:对于路由调用者而言,路由的终点无论是函数、页面还是数据,Rubik Router都提供一致的调用方式。
函数路由   另外,Rubik Router提供了基于Kotlin DSL的调用方式,提供了基于元注解的路由声明方式,让使用者可以更加简便、直观的调用其他组件提供的接口。  
@RRoute(path = "user") 
fun getUser(id : Int, name : String) : User? { 
…
}

用元注解把函数注册到路由

navigate {
	uri = "app://com.account/user"
	query {
"id" with 400
"name" with "zhangsan01" 
	}
result<User?> { user ->// 通过泛型指定接收数据类型
…
}
} 

通过Kotlin DSL调用其他组件提供的接口

Rubik Plugins:基于Gradle Plugin的组件管理和依赖管理工具

    Rubik gradle plugins 提供了组件定义、版本控制、maven发布、二进制依赖与源码依赖切换等能力,包括4个gradle plugin:
  • rubik:
    • 提供全局定义组件的能力,并根据全局定义自动启用rubik-context、rubik-root等插件

      rubik插件工程结构

      rubik {
      component {
      uri "app://com.cloud-file"
      		// uri 是组件的唯一 id,和路由根路径 
      dependencies {// 组件所依赖的其他组件uri
      uri ("app://com.local-file" ) 
      uri ("app://com.upload" )
      }
      source {// 定义的多种来源
      project (":lib-cloud-file") 
      maven { // 其他组件依赖自己的默认版本
      		version "0.2.0"
      		variant "english-debug" 
      }
      }
      }
      component { … }// 继续定义下一个组件
      }

      组件的定义方式

       

       

  • rubik-root:
    • 给App工程提供筛选组件能力,根据flavor、版本号筛选要打包进apk的业务组件
    • 提供组件的源码工程和aar切换的能力
组件的筛选与依赖方式切换

 

rubik {	
	packing { 
uri ("app://com.cloud-*") { // 筛选范围,uri表示用uri筛选,支持*匹配任意字符
projcetMode () // 筛选方式, projcetMode通过工程筛选一些组件
}
uri ("app://com.preview-file") {
mavenMode {// 筛选方式, mavenMode通过maven依赖aar筛选一些组件 
version "0.2.0"
		variant "netdisk-english-debug" 
}
} 
	 ……
}
} 

筛选组件的方式

 
  • rubik-context:
    • 提供把业务代码按flavor、版本号编译成aar 并发布到maven的能力
    • 提供辅助函数路由,把中间代码打包成context.jar ,并按版本号发布到maven的能力,并根据全局定义,为组件自动添加其他组件的中间代码依赖
组件及中间代码的发布和自动依赖  
  • rubik-test:
    • 给工程提供单元测试环境

最后

    希望Rubik能够帮助大家更便捷的实现组件化开发,也欢迎大家进行代码和技术层面的交流,如果你觉得我们做的还不错,请小伙伴们不要吝惜star、fork和watching: https://github.com/baidu/Rubik

 


相關推薦

2023-04-15

。至此,Compose Multiplatform 基本实现了全平台支持:iOS、Android、Windows、macOS、Linux 和 Web。 Compose Multiplatform 是用于跨多个平台共享 UI 的声明式框架,基于 Kotlin 和 Jetpack Compose 打造,由 JetBrains 和开源贡献者开发。 Jetpack Compos

2022-03-25

在官方招聘页面放出新的,而这个招聘信息则是泄漏了 Android Studio 的未来发展方向。根据招聘信息介绍,该职位是 Android Studio 高级软件工程师,在简介中 Google 写道: 我们正在 Android Studio 中启动一个新项目,以使其可用于 Andr

2022-08-24

Google I/O 大会上,谷歌宣布:官方正式支持将 Kotlin 作为 Android 开发的 First-Class(一等公民)语言。自此,Kotlin 开发商 JetBrains 和谷歌一直围绕 Kotlin 进行紧密合作,并共同创立了 Kotlin 基金会。 正如最初 I/O 公告中所强调的那

2022-10-28

Meta 发布了一篇博客表示,正在将其 Android 应用的 Java 代码迁移到 Kotlin,并分享了这一过程中的一些经验。 该公司认为,Kotlin 是一种流行的 Android 开发语言,与 Java 相比具有一些关键优势。“因此,在我们努力使我们的开发工

2023-04-16

了来自 Google 的最新消息:Google 内部几乎全在用 Kotlin 搞 Android 开发。 Kotlin 在 2016 年左右开始在 Android 社​​区中流行起来。 2017 年,谷歌宣布在 Android 上正式支持 Kotlin,并通过与 JetBrains 一起创建 Kotlin 基金会来发展这门语

2023-08-19

用者的反馈进行调整。 2020 年,我们将重点转向 iOS 与 Android 之间的代码共享,这是最常见的用例。我们希望吸引更多移动开发者使用 Kotlin Multiplatform,利用他们的反馈增强技术,准备进行更多改进,包括更好地支持其他目标。

2023-01-29

TheRouter 是由 Kotlin 编写,由货拉拉技术开源的,用于 Android 模块化开发的一整套解决方案框架。支持 KSP、支持 AGP8,不仅能对常规的模块依赖解耦、页面跳转,同时提供了模块化过程中常见问题的解决办法。例如:完美解决了模

2023-05-16

TheRouter 是由 Kotlin 编写,由货拉拉技术开源的,用于 Android 模块化开发的一整套解决方案框架。支持 KSP、支持 AGP8,不仅能对常规的模块依赖解耦、页面跳转,同时提供了模块化过程中常见问题的解决办法。例如:完美解决了模

2022-10-11

动应用中共享业务逻辑,具体来说是可通过 KMM 在 iOS 和 Android 应用中使用相同的业务逻辑代码。 关于 Kotlin Multiplatform 生态系统的演变的一些信息还包括有: Google 的 Android 团队分享了 Jetpack 中 Kotlin 多平台库的预览。作为

2023-09-12

于 2016 年首次正式发布 Kotlin 语言;2017 年,Google 宣布为 Android 版 Kotlin 提供一流支持。彼时,由于 Java(Android 的传统语言)被认为过于冗长,Kotlin 的受欢迎程度上升至 1%,并在当时的 TIOBE 指数中名列前 20。 接下来,Kotlin 耗

2023-11-14

该语言的第一波流行是在 2017 年,彼时 Google 宣布在 Android 上对 Kotlin 提供一流的支持,Kotlin 在 TIOBE 指数中也达到了近 1% 的峰值。但这一记录在本月被打破,目前 Kotlin 的评级为 1.15%。 TIOBE CEO Paul Jansen 评论

2024-05-23

用的移动数据库框架,基于 SQLCipher ,支持 iOS、macOS 和 Android。 目前 WCDB 发布了 2.1.5 版本,此版本的主要变更如下: 支持 WCDB Java/Kotlin 中的旧版 mmicu tokenizer 支持回滚压缩 提高 vacuum 的性能 将 valueOr 接口添加到 Optional

2023-04-16

2.0 一起工作。谷歌还与 JetBrains 密切合作,将 K2 集成到 Android Studio 和 Compose 编译器中,进一步提升开发者体验。

2023-11-20

周前宣布推出第一个稳定版本后,JetBrains 发布了 2024 年 Kotlin Multiplatform 的开发路线图。 其目标是在 2024 年对 Kotlin Multiplatform 核心技术、Compose Multiplatform、KMP 工具和 KMP 库进行一系列改进。 “我们致力于使Compose Multiplatform