上一节对 Navigation 配置进行了拓展,这节拓展 Navigation 导航,添加拦截功能,默认实现一个路由无法找到的拦截器,避免导航到未知路由时报错。在下一节状态管理中应用导航拦截。
这些功能都是在保证不破坏原框架的基础上进行的拓展。
NavControllerKtx
在 lib_compose navigation 包下添加 NavControllerKtx.kt 文件
拦截器接口
interface NavInterceptor{
/**
* 是否需要拦截
* @return Boolean true 拦截
*/
fun shouldIntercept(
route: String,
navOptions: NavOptions?,
navController: NavController
): Boolean
/**
*拦截后的导航逻辑
*/
fun navigate(navController: NavController,originalRoute:String)
}
拓展 NavController.navigate()
不足之处在于,拦截器没有优先级,只会执行先匹配到的拦截器。(暂时没有遇到需要的场景,需要时再添加)
fun NavController.navigate(route: String, interceptors:List<NavInterceptor>? = null ,builder: NavOptionsBuilder.() -> Unit){
val navOptions = navOptions(builder)
//是否有需要拦截的拦截器
val interceptor = interceptors?.find { it.shouldIntercept(route,navOptions,this) }
if (interceptor != null){
// 调用拦截器导航
interceptor.navigate(navController = this, originalRoute = route)
}else{
navigate(route,navOptions)
}
}
PageNotFind 拦截器
object NotFoundInterceptor:NavInterceptor{
override fun shouldIntercept(
route: String,
navOptions: NavOptions?,
navController: NavController
): Boolean {
// 如果是 404 页面不拦截
if (route == PageNotFoundScreen.route) return false
//Compose navigate 是使用 DeepLink 匹配模式,
//route 转换成 NavDeepLinkRequest 去 navController.graph 中匹配
val request = NavDeepLinkRequest.Builder.fromUri(NavDestination.createRoute(route).toUri()).build()
val requestMatch = navController.graph.matchDeepLink(request)
return requestMatch == null
}
override fun navigate(navController: NavController,originalRoute:String) {
navController.navigate(PageNotFoundScreen.route)
}
}
// 404 页面 需要在 NavHost 参数的 NavGraphBuilder 中配置
object PageNotFoundScreen: Screen("pageNotFound"){
override val root: String
get() = "route404"
}
Navigation Compose 集成到这里就结束了,后续开发中如果遇到其他需求我们再来拓展。