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>()
    //注册
    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
        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>()

    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
        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)
                    }
                }
            }
        }
    }
}

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

你可能感兴趣的:(Android 手写EventBus)