EventBus Kotlin实现源码解析

介绍:

使用第三方框架可以加快项目开发进度,为了加强对EventBus框架原理的理解同时更好掌握kotlin语言,这次我使用kotlin实现eventbus基本功能:注册,取消注册,消息传递,主线程,子线程事件传递。

为了更好理解通过下面几个流程图来说明:

EventBus注册流程

//注解注册
fun register(item: Object){
        //判断改对象是否已经注册
       var list : ArrayList<SubscrbileMethod>? = cacheMap?.get(item)
        if(list == null){
            list = findSubscrbileMethods(item)
            //将所有注解方法和对象绑定到map中
            list?.let { cacheMap?.put(item, it) }
        }
}

//获取改注解所有注解方法
fun findSubscrbileMethods(item:Object):ArrayList<SubscrbileMethod>{
        var list : ArrayList<SubscrbileMethod> = ArrayList()
        //找到类对象
        var clazz : Class<*> = item.`class`
        //循环查找父类带有注解的方法
        while(clazz != null){
            val name : String = clazz.name
            if(name.startsWith("java.") || name .startsWith("javax.")
              || name.startsWith("android.")){
                break
            }
            //找到类中所有方法
            var methods: Array<Method>? = clazz.declaredMethods
            methods?.forEach {
                var method = it
                //获取每一个方法所有Subscrbile注解
                var subscrbile=it.getAnnotation(Subscrbile::class.java)
                subscrbile?.let {
                    //找到注解参数
                    val types:Array<Class<*>> ? = method.parameterTypes
                    //只要一个参数的注解方法
                    if(types?.size == 1){
                        //获取注解参数
                        val threadMode : ThreadMode = it.threadMode
                        val subscrbileMethod : SubscrbileMethod = SubscrbileMethod(method,threadMode,types[0])
                        list.add(subscrbileMethod)
                    }else{
                        Log.w("EventBus","参数个数不只一个")
                    }
                }
            }
            clazz = clazz.superclass
        }
        return list
    }

消息通信流程

fun post(bean:EventBean){
        //变量cacheMap所有带有bean类型的方法并调用
        cacheMap?.forEach {
            var vm:Map.Entry<Object,List<SubscrbileMethod>> = it
            it.value.forEach {
                val subscrbileMethod: SubscrbileMethod = it
                //判断当前类型与传入类型关系
                if(it.type!!.isAssignableFrom(bean.javaClass)){
                    when(subscrbileMethod.mThreadMod){
                         ThreadMode.MAIN->{//主线程执行
                            if(Looper.myLooper() == Looper.getMainLooper()){//当前是在主线程
                                invoke(it,vm,bean)
                            }else{
                                handler?.post(Runnable {//handler切换到主线程
                                    invoke(it,vm,bean)
                                })
                            }
                        }
                        ThreadMode.BACKGROUND ->{//子线程执行
                            if(Looper.myLooper() != Looper.getMainLooper()){//当前是在子线程
                                invoke(it,vm,bean)
                            }else {
                                GlobalScope.launch(){//启动一个新的线程
                                    invoke(it,vm,bean)
                                }
                            }
                        }
                        else->{
                            Log.d(Tag,"can't match")
                        }
                    }
                }
            }
        }
    }

private fun invoke(subscrbileMethod: SubscrbileMethod, vm: Map.Entry<Object, List<SubscrbileMethod>>, bean: EventBean) {
        val method = subscrbileMethod.mMeath
        //调用注解方法
        method?.invoke(vm.key, bean)
}

注销流程

fun unregister(item: Object){
        var list : ArrayList<SubscrbileMethod>? = cacheMap?.get(item)
        list?.clear()
        cacheMap?.remove(item)
    }

总结:

自己敲了一遍会发现有很多细节需要考虑,尤其是在用kotlin语言时有些表达式一时还想不到,但习惯以后会发现kotlin语言比java确实要强大好用。

具体代码:传送门

发布了92 篇原创文章 · 获赞 27 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/zhuxingchong/article/details/93415929