前言
组件,就是对数据和方法的简单封装,功能单一,高类聚,是业务划分的最小粒度。组件化是基于可重用的目的,将大型软件系统按照分离关注点的形式,拆分成多个独立组件,使得整个软件是单个或多个组件元件组装起来。那组件之间如何通信呢?这就得益于ARouter。
Android原生的路由方案是Intent的显式和隐式跳转,显式需要对目标的引用,会导致不同页面的耦合,隐式集中配置在manifest中,不利于维护和管理。况且,在组件化开发中,各模块之间无法直接引用,那么,ARouter路由框架就派上用场了。
一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦
原理简述
ARouter通过APT技术,生成保存路径(路由path)和被注解(@Router)的组件类的映射关系的类,利用这些保存了映射关系的类,根据用户的请求postcard寻找到要跳转的目标地址,使用Intent跳转。所以,该框架的核心是利用APT生成的映射关系,APT的作用是在编译阶段扫描并处理代码中的注解,然后根据注解输出Java文件。
基本使用
添加依赖和配置,注意,每个使用到ARouter的Module都要引入
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
implementation 'com.alibaba:arouter-api:1.5.2'
kapt 'com.alibaba:arouter-compiler:1.5.2'
引入后需要注意的一点是:要在gradle.properties文件中加入下面这个,不然会编译不过去,这也是我遇到的一个小坑。
android.enableJetifier=true
在Application中初始化
if (isDebug()) { ARouter.openLog() //打印日志 ARouter.openDebug() //开启调试模式,线上需关闭 } ARouter.init(this)
在支持路由的页面上添加如下的注解,路径至少需要两级
@Route(path = "/home/HomeActivity") class HomeActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_home) } }
然后在另一个Activity中,进行跳转
ARouter.getInstance().build("/home/HomeActivity").navigation()
如果需要传递参数的话,可以这样做
ARouter.getInstance().build("/home/HomeActivity") .withString("name", "Uncle Xing") .withInt("age", 25) .withSerializable("user", User("Uncle Xing", 25)) .navigation()
然后在目标Activity中通过Autowired接收,ARouter会自动对字段进行赋值,无需主动获取
@Route(path = "/home/HomeActivity") class HomeActivity : AppCompatActivity() { @JvmField @Autowired var name = "" @JvmField @Autowired var age = 0 @JvmField @Autowired var user: User? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_home) initView() } private fun initView() { ARouter.getInstance().inject(this) findViewById(R.id.name).text = name findViewById (R.id.age).text = age.toString() findViewById (R.id.user).text = user.toString() } }
在组件化开发中,我们通常会有一些公共Module来作为共有功能,那这个时候就可以使用ARouter的依赖注入解耦,组件件的通信,首先我们要声明接口,其他组件通过这个接口来调用方法
interface MyProvider : IProvider { fun getData(): String }
实现类
@Route(path = "/common/MyProviderImpl") class MyProviderImpl : MyProvider { override fun getData(): String { return "Welcome to my blog" } override fun init(context: Context?) { } }
其他组件的Activity就可以这样调用
class MainActivity : AppCompatActivity() { /** * 当一个接口只有一个实现类的时候,Autowired可以不设置name */ @JvmField @Autowired(name = "/common/MyProviderImpl") var myProvider: MyProvider? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initView() } private fun initView() { ARouter.getInstance().inject(this) findViewById(R.id.provider_text).text = myProvider?.getData() } }
上面是使用依赖注入的方式,通过注解标注字段,即可使用,无需主动获取,除此之外,我们也可以使用赖查找的方式,比如上面的代码我们也可以写成这样
class MainActivity : AppCompatActivity() { var myProvider: MyProvider? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initView() } private fun initView() { // ARouter.getInstance().inject(this) 这种方式不需要这句 myProvider = ARouter.getInstance().build("/common/MyProviderImpl").navigation() as MyProvider /** * 发现的方式有byName和byType,如果一个接口只有一个实现的话,也可以使用byType,可以写成 * myProvider = ARouter.getInstance().navigation(MyProvider::class.java) */ findViewById(R.id.provider_text).text = myProvider?.getData() } }
我们也可以动态注册路由,这样,目标页面和服务就可以不标注 @Route 注解。不过,一般组件化项目都不会这样干,适合部分插件化架构的项目或其他场景。
ARouter.getInstance().addRouteGroup { it["/home/HomeActivity"] = RouteMeta.build( RouteType.ACTIVITY, //路由信息 HomeActivity::class.java, //目标class "/home/HomeActivity", //path "home", //Group,尽量保持和path的第一段相同 0, 0 ) }
注意:同一批次仅允许相同 group 的路由信息注册
到此这篇关于Android组件化工具ARouter使用方法详细分析的文章就介绍到这了,更多相关Android ARouter内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!