我的学习手册 - ARouter了解了一下下

目录

我的学习手册 - 热更新了解了一下下
我的学习手册 - Glide了解了一下下
我的学习手册 - 进程保活了解了一下下
我的学习手册 - EventBus了解了一下下
我的学习手册 - ARouter了解了一下下

首先了解页面Activity跳转,只要获取到了clazz对象,那么所有的Activity都可以跳转

    startActivity(mContext,clazz)

简单思路:

  • 首先在底层模块中需要一个存放key和value的map,用于存放地址和Activity的class对象,

  • 然后在每一个需要跨模块跳转的添加地址和class存入方法的工具类

  • 之后App模块集成所有Module,在App模块中在合适的地方调用每一个Module的这些个方法工具类,就把需要的Activity的Class对象存入了

  • 最后在需要调用的地方将需要的Activity的Class对象取出

进阶思路:

  • 通过注解和注解处理器,将所有添加注解的Activity的path和class通过文件生成器自动生成,生成的文件需要固定使用同一个包名,但是文件名不能一样,这里生成的文件全部实现一个统一接口,这样会方便调用
  • 之后在初始化的时候通过反射获取该包名下的所有类,并且实例化调用统一方法
一、ARouter工具
    // 需要一个Map 存放当前App中所有需要跳转的Activity的Class对象
    private val activityMap: HashMap<String, Class<out Activity>> = hashMapOf()
    
    /*** 将地址和Activity的Class对象存入 ***/
    fun setActivityClazz(path: String, clazz: Class<out Activity>) {
        if (path.isNotEmpty()) {
            activityMap.put(path, clazz)
        }
    }

    /*** 读取存放的Activity ***/
    fun getActivityClazz(path: String): Class<out Activity>? {
        return activityMap[path]
    }
二、IRouter公共接口
interface IRouter {
    fun putActivity()
}
三、底层路径
object RouterPath{
    const val MemberActivity = "/Member/MemberActivity"
    const val NewsActivity = "/News/NewsActivity"
}
四、Module数据存入

将Router模块依赖到app和其他需要跳转的所有module,在每一个需要跳转的module中创建一个ModuleRouter工具实现IRouter,这个时候可以获取到需要跳转的Class对象,存入ARouter组件中,例如:

object MemberRouter : IRouter {
    
    override fun putActivity() {
        ARouter.get().setActivityClazz(RouterPath.MemberActivity, MemberActivity::class.java)
    }
}
五、App中的数据存入与获取
    // 在合适的地方进行调用 存入所有模块中需要跳转的Activity对象
    MemberRouter.putActivity()
    NewsRouter.putActivity()
   
    // 在Member模块中跳转到News模块中
    val clazz = ARouter.get().getActivityClazz(RouterPath.NewsActivity)
    startActivity(Intent(this,clazz))

到这里一个简单的路由组件的实现就完成了,基本思路就是通过中间件来存入和获取需要跳转的Activity的Class对象

六、进阶-注解 仿照ARouter
1、创建注解

创建Kotlin Library (annotaion)

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
annotation class Route(val path: String)
2、创建注解处理器

创建Kotlin Library (annotation_compiler)

我的AS是3.6.2都加上才会进行处理
implementation 'com.google.auto.service:auto-service:1.0-rc6'
kapt 'com.google.auto.service:auto-service:1.0-rc6'

// 自动注册
@AutoService(Processor::class)
// 表示使用Java8和build.gradle中保持同步
@SupportedSourceVersion(SourceVersion.RELEASE_8)
// 只进行解析Route注解
@SupportedAnnotationTypes("com.memo.annotation.Route")
class RouteCompiler : AbstractProcessor() {
    
    /*** 文件生成器 ***/
    lateinit var filer: Filer
    /*** 日志打印 ***/
    lateinit var logger: Messager

    /*** 初始化 ***/
    override fun init(environment: ProcessingEnvironment) {
        super.init(environment)
        filer = environment.filer
        logger = environment.messager
    }

    /*** 处理生成代码文件 ***/
    override fun process(set: MutableSet<out TypeElement>, environment: RoundEnvironment): Boolean {
        // 拿到Route注解的节点
        // 有三种注解节点  类节点TypeElement 方法节点ExecutableElement 变量节点VariableElement
        val routeSets = environment.getElementsAnnotatedWith(Route::class.java)
        // 存放path和activity
        val activityMap = HashMap<String, String>()
        routeSets.forEach {
            val typeElement = it as TypeElement
            // 地址
            val path = typeElement.getAnnotation(Route::class.java).path
            // Activity全路径
            val activityName = typeElement.qualifiedName.toString()
            // 把地址和Activity的带包名的地址存入
            activityMap[path] = activityName

            logger.printMessage(Diagnostic.Kind.WARNING, "发现路由组件-->$activityName")
        }

        // 生成文件
        if (activityMap.isNotEmpty()) {
            // 生成唯一的文件名称 防止文件重复 有多个Module多次调用
            // 按照ARouter这里是module名称拼接 偷懒了
            val fileName = "RouterUtils_${System.currentTimeMillis()}"
            try {
                // 创建文件
                // 使用use方法自动关闭io流
                filer.createSourceFile(fileName).openWriter().use {
                    it.write(createFileContent(fileName, activityMap))
                }
            } catch (e: Exception) {
                logger.printMessage(Diagnostic.Kind.ERROR, e.toString())
            }

        }

        return false
    }


    /**
     * 创建Java文件内容
     * 这里可以使用JavaPoet或者KotlinPoet代替 依赖相应的包
     * 我用的不熟练所以就直接字符串拼接了
     */
    private fun createFileContent(fileName: String, activityMap: HashMap<String, String>): String {
        val buffer = StringBuffer()
        buffer.append(
            "package com.memo.router.utils;\n" +
                    "import com.memo.router.core.ARouter;\n" +
                    "import com.memo.router.core.IRouter;\n" +
                    "public class $fileName implements IRouter {\n" +
                    "@Override\n" +
                    "public void putActivity() {\n"
        )
        activityMap.forEach { (path, activity) ->
            buffer.append("ARouter.get().setActivityClazz(\"$path\", $activity.class);\n")
        }
        buffer.append("}\n}")
        return buffer.toString()
    }
}
3、调用putActivity方法

在初始化的时候可以传入ApplicationContext,利用这个进行页面跳转
之前我们在写文件的时候是固定包名的com.memo.router.utils,那么我们可以通过反射来找到对应包名下面的所有文件,ClassUtils直接从Arouter中CV过来

        val files = ClassUtils.getFileNameByPackageName(mContext, "com.memo.router.utils")
        files.forEach {
            try {
                val clazz = Class.forName(it)
                // 查看是否实现了IRouter
                if (IRouter::class.java.isAssignableFrom(clazz)) {
                    // 开始调用putActivity方法
                    (clazz.newInstance() as IRouter).putActivity()
                }
            } catch (e: Exception) {
            }
        }
4、添加注解并且跳转
    /*** 通过ApplicationContext 直接跳转 ***/
    fun startActivity(path: String, bundle: Bundle? = null) {
        val clazz = activityMap[path]
        clazz?.let {
            val intent = Intent(mContext, it)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            if (bundle != null) intent.putExtras(bundle)
            mContext.startActivity(intent)
        }
    }
    
    ARouter.get().startActivity(RouterPath.NewsActivity)
源码

最后放上源码地址 ARouter了解了一下下

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343