Android组件化中的Arouter学习

假设现在有两个业务组件登录和问答模块之间需要进行通信,可能会想到用反射的方式,是可以但是会影响性能,而写的代码比较多类名这些要记清楚。

路由可以看做表,每个map对应一张表

我们可以试着这么写,完成MainActivity跳转到LoginActivity,LoginActivity再跳转到WendaActivity。

新建一个libRouter的library

新建一个Router类进行路由表的注册和启动

kotlin 复制代码
class Router private constructor() {

    //先通过组名找到map再通过map找到对应的类名
    final val groupMap: HashMap<String, HashMap<String, Class<*>>> = HashMap()
    //最终将LoginActivity,WendaActivity注册到routeMap里面去
    final val routeMap:HashMap<String,Class<*>> =HashMap()

    object Holder {
        var INSTANCE = Router()
    }

    fun getInstance(): Router {
        return Holder.INSTANCE
    }

    //注册
    fun register(path:String,clz:Class<*>){
        val strArray: Array<String> = path.split("/").toTypedArray()
        if(strArray.size>2){
            var groupName:String=strArray[1]
            var routeName=path
            var group:HashMap<String,Class<*>>?=null
            if(groupMap.containsKey(groupName)){
                group=groupMap.get(groupName)
            }
            if(group==null){
                group= HashMap()
                groupMap.put(groupName,group)
            }
            if(group!=null){
                group.put(routeName,clz)
            }
        }
    }
    //启动
    fun startActivity(activity:Activity,path: String){
        val strArray: Array<String> = path.split("/").toTypedArray()
        if(strArray.size>2){
            var groupName:String=strArray[1]
            var routeName=path
            var group:HashMap<String,Class<*>>?=null
            if(groupMap.containsKey(groupName)){
                group=groupMap.get(groupName)
            }
            if(group!=null && group.containsKey(routeName)){
                val clz=group.get(routeName)
                activity.startActivity(Intent(activity,clz))
            }
        }
    }


}

MainActivity跳转LoginActivity

kotlin 复制代码
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Router.Holder.INSTANCE.startActivity(this,"/login/LoginActivity")
    }
}

LoginActivity跳转WendaActivity

kotlin 复制代码
class LoginActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
    }

    fun onClickView(view: View) {


      Router.Holder.INSTANCE.startActivity(this,"/wenda/WendaActivity")

    }
}

loginActivity布局增加点击事件

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LoginActivity">

    <TextView
        android:onClick="onClickView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="LoginActivity"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Application注册路由表

kotlin 复制代码
class SunBeachApplication:Application() {


    override fun onCreate() {
        super.onCreate()
        Router.Holder.INSTANCE.register("/login/LoginActivity",LoginActivity::class.java)
        Router.Holder.INSTANCE.register("/wenda/WendaActivity",WendaActivity::class.java)

    }
}

运行app从MainActivity跳转到LoginActivity

点击LoginActivity跳转到WendaActivity

但也有问题并且如果要跳转的Activity比较多,Application里的onCreate方法需要注册比较多

如果我们在Router类进行添加的话就会出现无法识别出几个类的问题

所以我們需要一个注解处理器,由Activity去扫描,扫描到添加进来。

这个时候我们再来看一下Arouter是怎么实现的。

Arouter核心原理:

当我们使用Arouter的注解处理器的时候,就会帮我们生成相应的类,Arouter$$Group $ $login就是login的group,而Arouter $ $Root $ $login就是去查找到group并调用group的方法

可以看到Arouter$ $ Root $ $ login通过传递routes将Arouter$ $Group $ $login的class添加到Map中。

而Arouter$ $Group $ $login里当调用了loadInto方法的话就会将LoginActivity注册进来

将相应的信息放到RouteMeta当中,RouteMeta就是一个包装类,封装了当前的一些信息,主要通过RouteMeta找到对应的class进行跳转或者参数传递。

当我们在使用Arouter的时候都需要进行init()初始化

这个_ARouter就是路由控制器。

这里主要是获取之前保存的一些信息,而不用for循环去遍历,这样下次可以直接用。

第一次通过getFileNameByPackageName把指定包下面的所有文件找出来,也就是生成的下面包的文件

也指定了要找对应包名的文件

并返回到routerMap的集合里去

然后再去遍历routerMap

而当第二次,缓存到本地后,直接读取拿到信息,就不用再去找。


这个时候在遍历routerMap的时候就会拿到这个root文件去调用loadInto方法

loadInto方法的具体实现也就是生成的那些类中

它会找到生成的group直接put到分组当中,分组当中提供了一个方法

通过这个方法可以将path,class这些信息放到一个map当中。因为生成文件中有很多group,有grouplogin,groupmain,要找到这些group调用loadInto方法,这样我们通过传入path路径,就能找到RouteMeta,就可以拿到class。

而当我们要去跳转,这个时候会进行build操作

会返回一个Postcard对象里面也包含了一些信息

接着继续点进去发现navigation这个方法调用了LogisticsCenter.completion(postcard)

调用loadInto这个方法其实也就是对应下面的方法。

相关推荐
喜欢猪猪9 分钟前
Java技术专家视角解读:SQL优化与批处理在大数据处理中的应用及原理
android·python·adb
JasonYin~2 小时前
HarmonyOS NEXT 实战之元服务:静态案例效果---手机查看电量
android·华为·harmonyos
zhangphil2 小时前
Android adb查看某个进程的总线程数
android·adb
抛空2 小时前
Android14 - SystemServer进程的启动与工作流程分析
android
Gerry_Liang4 小时前
记一次 Android 高内存排查
android·性能优化·内存泄露·mat
天天打码5 小时前
ThinkPHP项目如何关闭runtime下Log日志文件记录
android·java·javascript
爱数学的程序猿8 小时前
Python入门:6.深入解析Python中的序列
android·服务器·python
brhhh_sehe8 小时前
重生之我在异世界学编程之C语言:深入文件操作篇(下)
android·c语言·网络
zhangphil8 小时前
Android基于Path的addRoundRect,Canvas剪切clipPath简洁的圆形图实现,Kotlin(2)
android·kotlin
Calvin8808289 小时前
Android Studio 的革命性更新:Project Quartz 和 Gemini,开启 AI 开发新时代!
android·人工智能·android studio