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这个方法其实也就是对应下面的方法。

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui