Android 手写EventBus
2019-07-14 本文已影响60人
裴庆圣
EventBus使用了观察者模式,核心是通过反射invoke执行注册方法,今天我们就来通过简单的代码写一个EventBus
- 首先定义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) {
}
}
- 定义注解 Subscribe
@Target(AnnotationTarget.FUNCTION)
annotation class Subscribe(val threadMode: ThreadMode = ThreadMode.MAIN)\
- 定义 ThreadMode
enum class ThreadMode {
MAIN, BACKGROUND
}
ok 定义好上面3个类之后,已经成功一半了
现在,我们开始完善EventBus 这个类,来完善 其中3个常用的方法
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
unregister(subscriber: Any)
fun unregister(subscriber: Any) {
sub.remove(subscriber)
}
很简单,WeakHashMap中移除
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)
}
}
}
}
}
}
简单的展示了其核心思想,实际使用中应考虑,非空判断,线程池执行,定义单独的类来管理注册的方法,等等