Android 手写EventBus

EventBus使用了观察者模式,核心是通过反射invoke执行注册方法,今天我们就来通过简单的代码写一个EventBus

  1. 首先定义EventBus 类
    定义好使用4个方法getDefault() ,register(subscriber: Any),unregister(subscriber: Any),post(event: Any)
class EventBus {
    companion object {
        private var instance: EventBus? = null
            get() {
                if (field == null) {
                    field = EventBus()
                }
                return field
            }

        @Synchronized
        fun getDefault(): EventBus {
            return instance!!
        }
    }

    fun register(subscriber: Any) {
        
    }

    fun unregister(subscriber: Any) {

    }

    fun post(event: Any) {
        
    }
}
  1. 定义注解 Subscribe
@Target(AnnotationTarget.FUNCTION)
annotation class Subscribe(val threadMode: ThreadMode = ThreadMode.MAIN)\
  1. 定义 ThreadMode
enum class ThreadMode {
    MAIN, BACKGROUND
}

ok 定义好上面3个类之后,已经成功一半了

现在,我们开始完善EventBus 这个类,来完善 其中3个常用的方法

  1. register(subscriber: Any)
  //key 是注册类  value被Subscribe注解的方法List
   private  val sub = WeakHashMap<Any, ArrayList<Method>>()
    //注册
    fun register(subscriber: Any) {
        //获取注册类的 List,没有则新建
        var methods = sub.get(subscriber)
        if (methods == null) {
            methods = ArrayList()
            sub.put(subscriber, methods)
        }
        //通过反射,获取注册类的所有方法
        val ms = subscriber.javaClass.declaredMethods
        var annotations: Array<Annotation>
        for (method in ms) {
            annotations = method.annotations
            if (!annotations.isEmpty()) {
                for (an in annotations) {
                    //找到被Subscribe注解的方法,放入集合
                    if (an is Subscribe) {
                        methods.add(method)
                    }
                }
            }
        }
    }

找到注册对象中的注解方法,放入WeakHashMap

  1. unregister(subscriber: Any)
fun unregister(subscriber: Any) {
        sub.remove(subscriber)
    }

很简单,WeakHashMap中移除

  1. post(event: Any)
fun post(event: Any) {
        //遍历 事件列表
        for ((key, value) in sub) {
            for (method in value) {
                //注解方法中,有参数和post中的参数一致的,得到其方法
                if (method.genericParameterTypes[0] == event.javaClass) {
                    //获取注解参数
                    val an = method.getAnnotation(Subscribe::class.java)
                    //注解参数是主线程的,放入主线程执行
                    if (an.threadMode == ThreadMode.MAIN) {
                        Handler(Looper.getMainLooper()).post {
                            method.invoke(key, event)
                        }
                    } else {
                        //后台的,开启子线程执行
                        Thread {
                            method.invoke(key, event)
                        }.start()
                    }
                }
            }
        }
    }

根据post中的event类 和列表中找到注解方法的参数一样的,通过invoke执行,根据注解的参数,确定执行的方法在主线程还是子线程

完整的EventBus 类

class EventBus {

    private val sub = WeakHashMap<Any, ArrayList<Method>>()

    companion object {
        private var instance: EventBus? = null
            get() {
                if (field == null) {
                    field = EventBus()
                }
                return field
            }

        @Synchronized
        fun getDefault(): EventBus {
            return instance!!
        }
    }

    fun register(subscriber: Any) {
        var methods = sub.get(subscriber)
        if (methods == null) {
            methods = ArrayList()
            sub.put(subscriber, methods)
        }
        val ms = subscriber.javaClass.declaredMethods
        var annotations: Array<Annotation>
        for (method in ms) {
            annotations = method.annotations
            if (!annotations.isEmpty()) {
                for (an in annotations) {
                    if (an is Subscribe) {
                        methods.add(method)
                    }
                }
            }
        }
    }

    fun unregister(subscriber: Any) {
        sub.remove(subscriber)
    }

    fun post(event: Any) {
        for ((key, value) in sub) {
            for (method in value) {
                if (method.genericParameterTypes[0] == event.javaClass) {
                    val an = method.getAnnotation(Subscribe::class.java)
                    if (an.threadMode == ThreadMode.MAIN) {
                        Handler(Looper.getMainLooper()).post {
                            method.invoke(key, event)
                        }
                    } else {
                        method.invoke(key, event)
                    }
                }
            }
        }
    }
}

简单的展示了其核心思想,实际使用中应考虑,非空判断,线程池执行,定义单独的类来管理注册的方法,等等

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 项目到了一定阶段会出现一种甜蜜的负担:业务的不断发展与人员的流动性越来越大,代码维护与测试回归流程越来越繁琐。这个...
    fdacc6a1e764阅读 3,226评论 0 6
  • EventBus源码分析 Android开发中我们最常用到的可以说就是EventBus了,今天我们来深入研究一下E...
    BlackFlag阅读 515评论 3 4
  • EventBus是一个Android开源库,其使用发布/订阅模式,以提供代码间的松耦合。EventBus使用中央通...
    壮少Bryant阅读 669评论 0 4
  • EventBus基本使用 EventBus基于观察者模式的Android事件分发总线。 从这个图可以看出,Even...
    顾氏名清明阅读 644评论 0 1
  • 简介 前面我学习了如何使用EventBus,还有了解了EventBus的特性,那么接下来我们一起来学习EventB...
    eirunye阅读 470评论 0 0