CLAUDE.md 8.0 KB

Router 模块

模块概述

Router 模块是基于注解的页面路由框架,提供了 Android 应用内的页面跳转、参数传递、拦截器机制和深链接支持。该模块采用编译时代码生成的方式,实现了高性能的路由分发机制。

模块结构

子模块组成

  • router-annotation: 路由注解定义模块
  • router-api: 路由API和核心实现模块
  • router-compiler: 编译时代码生成器

核心组件

  • Router: 路由管理器,提供统一的路由API
  • UriHandler: URI处理器抽象类
  • ActivityHandler: Activity跳转处理器
  • DialogFragmentHandler: 对话框Fragment处理器
  • UriInterceptor: 路由拦截器接口

主要功能

1. 路由注解系统

  • @RouterUri: 路由URI注解,支持路径、拦截器配置
  • @BindExtra: 参数绑定注解,自动解析Intent参数
  • 支持Activity、Fragment、UriHandler的路由注册

2. 多种路由模式

  • 路径路由: 基于path的简单路由 (/test)
  • 完整URI路由: 支持scheme+host+path (weparty://test/path)
  • 正则路由: 基于正则表达式的灵活匹配
  • 优先级路由: 支持路由优先级配置

3. 参数传递与绑定

  • 自动参数绑定机制
  • 支持各种数据类型参数
  • Intent参数的类型安全处理

4. 拦截器机制

  • 链式拦截器调用
  • 支持请求拦截和修改
  • 可配置拦截器执行顺序

5. 深链接支持

  • 外部应用跳转支持
  • 系统深链接处理
  • RouterDeepLinkActivity统一入口

核心类和接口

Router (单例)

object Router {
    // 构建路由请求
    fun build(ctx: Context, path: String, fm: FragmentManager? = null): UriRequest
    
    // 启动路由
    fun startUri(request: UriRequest)
    
    // 获取路由实例
    fun <T> getRouterInstance(path: String): T?
    
    // 绑定参数
    fun bind(obj: Any)
    
    // 获取深链接
    fun getDeepLink(path: String): String
}

注解定义

@RouterUri(
    path: Array<String> = [],           // 路由路径
    interceptors: Array<KClass<*>> = [], // 拦截器列表
    desc: String = "Empty description"   // 描述信息
)

@BindExtra(
    name: String                        // 参数名称
)

UriHandler

abstract class UriHandler {
    abstract fun canHandle(request: UriRequest): Boolean
    abstract fun handle(request: UriRequest)
    
    // 内部调用链,包含拦截器处理
    fun handleInner(request: UriRequest)
}

UriRequest

class UriRequest(
    val context: Context,
    val path: String,
    val fragmentManager: FragmentManager?
) {
    // 添加参数
    fun putExtra(key: String, value: Any): UriRequest
    
    // 启动路由
    fun start()
}

使用方式

1. Activity 路由

// 注册路由
@RouterUri(path = ["/test"], interceptors = [TestUriInterceptor::class])
class TestRouterBindActivity : AppCompatActivity() {
    
    @BindExtra(name = "extra_test")
    var extraTest: String? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Router.bind(this) // 必须手动调用参数绑定
    }
}

// 跳转调用
Router.build(context, "/test")
    .putExtra("extra_test", "测试参数")
    .start()

2. UriHandler 路由

// scheme + host 路由
@RouterUri(
    scheme = "weparty",
    host = "test",
    interceptors = [TestUriInterceptor::class]
)
class TestUriHandler : UriHandler() {
    
    @BindExtra(name = "extra_test")
    var extraTest: String? = null // 自动绑定,无需调用bind
    
    override fun canHandle(request: UriRequest): Boolean {
        return true
    }
    
    override fun handle(request: UriRequest) {
        // 处理路由逻辑
    }
}

// 跳转调用
Router.build(context, "weparty://test")
    .putExtra("extra_test", "测试参数")
    .start()

3. 正则路由

@RouterUri(
    regex = "http(s)?://(.*\\.)?(weparty)\\.(com|info|cn).*",
    priority = 2 // 数字越大优先级越高
)
class WebViewActivity : AppCompatActivity()

// 匹配调用
Router.build(context, "https://weparty.com/test")
    .start()

4. 拦截器使用

class TestUriInterceptor : UriInterceptor {
    override fun intercept(chain: UriInterceptor.Chain) {
        val request = chain.request()
        
        // 可以修改请求参数
        // val newRequest = request.newBuilder().putExtra("key", "value").build()
        
        // 继续执行
        chain.proceed(request)
        
        // 或者终止执行
        // chain.abort()
    }
}

5. Fragment 实例获取

@RouterUri(path = ["/bind_fragment"])
class BindFragment : Fragment() {
    @BindExtra(name = "extra_test")
    var extraTest: String? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Router.bind(this)
    }
}

// 获取Fragment实例
val fragment = Router.getRouterInstance<Fragment>("/bind_fragment")

6. 深链接配置

<!-- AndroidManifest.xml -->
<activity
    android:name="com.adealink.frame.router.RouterDeepLinkActivity"
    android:configChanges="keyboardHidden|orientation|screenSize">
    
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="weparty" />
    </intent-filter>
</activity>
# 触发深链接测试
adb shell am start -W -a android.intent.action.VIEW -d "weparty://test" com.your.package

编译时代码生成

注解处理器

  • RouterAnnotationProcessor: 主注解处理器
  • RouterUriHandler: 处理@RouterUri注解
  • BindHandler: 处理@BindExtra注解
  • InterceptorHandler: 处理拦截器注解

生成的代码

// 为带@RouterUri的类生成
class TestActivity_IRouterInit : IRouterInit {
    override val pathToClazzMap = mapOf("/test" to TestActivity::class.java)
}

// 为带@BindExtra的类生成
class TestActivity_IBinder : IBinder {
    override fun bind(obj: Any) {
        if (obj is TestActivity) {
            obj.extraTest = obj.intent.getStringExtra("extra_test")
        }
    }
}

性能优化

1. 缓存策略

  • pathToHandlerCache: UriHandler实例缓存 (LRU 100)
  • classNameToBinderCache: 参数绑定器缓存 (LRU 100)
  • classNameToInterceptorCache: 拦截器缓存 (LRU 100)

2. 懒加载机制

  • 路由映射按需加载,避免应用启动时全量初始化
  • SPI服务发现机制,动态发现路由配置

3. 实例管理

  • 路由实例不缓存,避免Activity内存泄漏
  • Handler缓存复用,减少反射开销

依赖关系

router-annotation 依赖

  • 无外部依赖,纯注解定义

router-api 依赖

  • androidx.core.ktx - Android核心扩展
  • androidx.appcompat - AppCompat支持
  • frame:spi - 服务发现机制
  • frame:base - 基础框架
  • router-annotation - 注解定义

router-compiler 依赖

  • Java注解处理器相关依赖

构建配置

// 应用模块
implementation "com.wenext.android:frame-router-api:6.0.0"
kapt "com.wenext.android:frame-router-compiler:6.0.0"

// 或在公共依赖中
api "com.wenext.android:frame-router-api:6.0.0"

注意事项

  1. 参数绑定: Activity需要手动调用Router.bind(this),UriHandler自动绑定
  2. 字段访问: @BindExtra注解的字段必须为public
  3. 实例缓存: 不要缓存getRouterInstance()返回的实例,避免内存泄漏
  4. 拦截器顺序: 拦截器按注解中定义的顺序执行
  5. 路由优先级: 精确匹配优先于正则匹配,priority数值越大优先级越高
  6. 深链接处理: 需要在AndroidManifest.xml中正确配置RouterDeepLinkActivity
  7. 编译配置: 需要正确配置kapt处理器,确保代码生成正常
  8. SPI配置: 依赖SPI模块的服务发现机制,确保相关配置正确