作者:Season3266
https://juejin.cn/post/7167760843021484039
Butterfly 是一个全功能的路由框架,不仅支持Activity、Fragment和DialogFragment,只支持 Compose UI的路由。小巧灵活,功能强大,提供了统一的API,你无需关心目的地是什么,在哪里,只需要提供一个scheme,Butterfly 便会导航至正确的地方。
话不多说,先看下Butterfly支持的功能列表。
功能列表
支持导航Activity 支持导航Fragment 支持导航DialogFragment 支持导航Compose UI 支持导航Action 支持导航参数传递和解析 支持获取导航返回结果 支持导航拦截器 支持Fragment和Compose UI回退栈 支持Fragment和Compose UI组管理 支持Fragment和Compose UI启动模式,如SingleTop、ClearTop 支持组件化通信
导航和参数传递
耳听为虚,眼见为实,如此强大的功能,没有几个示例怎么能行,来看一眼基本的导航功能:
@Agile("test/activity")
class AgileTestActivity : AppCompatActivity()
@Agile("test/fragment")
class TestFragment : Fragment()
@Agile("test/dialog")
class TestDialogFragment : DialogFragment()
//导航
Butterfly.agile("test/xxx").carry()
//或者导航并获取返回数据
Butterfly.agile("test/xxx")
.carry {
val result = it.getStringExtra("result")
binding.tvResult.text = result
}
如上所示,导航就是这么简单,无论目的地是什么、在何方,只需要一个scheme即可完成路由跳转。 scheme没有任何限制,可以是任意字符串,也可以是标准scheme,如butterfly://home/path
等。
在导航的过程中,参数传递也是必不可少的一环,Butterfly提供两种方式供你选择,一是通过拼接scheme的形式,如test/activity?paramA=123¶mB=abc
,即可将paramA和paramB传递至目的地,二是通过调用params方法,传递需要的数据,如:
//拼接scheme
Butterfly.agile("test/scheme?a=1&b=2").carry()
//调用params
Butterfly.agile("test/scheme?a=1&b=2")
.params("intValue" to 1)
.params("booleanValue" to true)
.params("stringValue" to "test value")
.carry()
如上所示,拼接scheme和调用params方法可以同时进行,在导航目的地可以获取到传递的所有的参数,params方法可以传递Bundle支持的任意类型的参数。
在目的地接受参数:
//在导航目的地页面,可通过参数的key字段来获取传递的参数值
@Agile("test/scheme")
class AgileTestActivity : AppCompatActivity() {
val a by lazy { intent?.getStringExtra("a") ?: "" }
val b by lazy { intent?.getStringExtra("b") ?: "" }
val intValue by lazy { intent?.getIntExtra("intValue", 0) ?: 0 }
}
//除了手动解析参数以外,还可以装备Bracer来实现全自动进行参数解析
@Agile("test/scheme")
class AgileTestActivity : AppCompatActivity() {
val a by params<String>()
val b by params<String>()
val intValue by params<Int>()
}
Bracer 使用方式详情见: https://github.com/ssseasonnn/Bracer
Compose 导航
Compose 作为Android全新的UI框架异军突起,越来越多的项目正在大量使用Compose,因此支持Compose导航已经刻不容缓。
@Agile("test/compose")
@Composable
fun HomeScreen() {
Box {
...
}
}
//导航到HomeScreen页面
Butterfly.agile("test/compose").carry()
如上所示,Compose的导航和Activity或Fragment的导航完全一致,统一的API使得简单易用程度得到更进一步的提高。
Compose 导航中的参数传递和获取与Activity或Fragment几乎相同,传递参数同样支持拼接scheme和调用params参数。获取参数只需要给Compose组件添加一个Bundle参数,随后即可通过该bundle参数获取导航中传递的参数。
@Agile("test/compose")
@Composable
fun HomeScreen(bundle: Bundle) {
val a by bundle.params<Int>()
val b by bundle.params<Int>()
val booleanValue by bundle.params<Boolean>()
Box {
Text(text = a)
}
}
//拼接scheme
Butterfly.agile("test/compose?a=1&b=2").carry()
//或者调用params
Butterfly.agile("test/compose?a=1&b=2")
.params("intValue" to 1)
.params("booleanValue" to true)
.params("stringValue" to "test value")
.carry()
路由拦截器
拦截器是一个很实用的功能,可以提供强大的路由控制功能,如登录检测、AB测试等功能。Butterfly提供两种作用域的拦截器:全局拦截器和一次性拦截器,可针对不同使用场景灵活选择。
首先定义好拦截器功能:
//自定义拦截器
class TestInterceptor : ButterflyInterceptor {
override fun shouldIntercept(agileRequest: AgileRequest): Boolean {
//检测是否需要拦截
return true
}
override suspend fun intercept(agileRequest: AgileRequest) {
//处理拦截逻辑
println("intercepting")
delay(5000)
println("intercept finish")
}
}
配置全局拦截器:
//添加全局拦截器
ButterflyCore.addInterceptor(TestInterceptor())
//跳过所有全局拦截器
Butterfly.agile("test/scheme").skipGlobalInterceptor().carry()
配置一次性拦截器:
//仅当前导航使用该拦截器
Butterfly.agile("test/scheme")
.addInterceptor(TestInterceptor())
.carry()
拦截器提供了suspend的intercept方法,聪明的你应该一眼就能明白它的强大之处。