Android开发经验谈Android开发

kotlin EventBus

2020-04-08  本文已影响0人  折剑游侠

用kotlin简单的实现一下EventBus,直接上代码。

//事件订阅注解
@Target(AnnotationTarget.FUNCTION)
@Retention(value = AnnotationRetention.RUNTIME)
annotation class Subscribe(val threadModel: ThreadModel = ThreadModel.POSTING)
enum class ThreadModel {
    //同事件发起线程
    POSTING,
    //主线程
    MAIN,
    //子线程
    ASYNC
}
class SubscribeMethod(
    //订阅方法
    var method: Method,
    //线程模式
    var threadModel: ThreadModel,
    //参数类型
    var eventType: Class<*>
)
object AndroidBus {
    //订阅者和事件缓存map
    private val map: MutableMap<Any, List<SubscribeMethod>> = mutableMapOf()
    private val handler = Handler(Looper.getMainLooper())
    private val executors = Executors.newCachedThreadPool()

    /**
     * 注册
     * @param subscribe
     */
    fun register(subscribe: Any) {
        var list = map[subscribe]
        if (list == null) {
            list = getSubscribeMethods(subscribe)
            map[subscribe] = list
        }
    }

    /**
     * 取消注册
     * @param subscribe
     */
    fun unRegister(subscribe: Any) {
        val list = map[subscribe]
        if (list != null) {
            map.remove(subscribe)
        }
    }

    /**
     * 获取订阅方法
     * @param subscribe
     */
    private fun getSubscribeMethods(subscribe: Any): List<SubscribeMethod> {
        val list: MutableList<SubscribeMethod> = mutableListOf()
        val clazz = subscribe.javaClass
        val name = clazz.name
        if (name.startsWith("java.") ||
            name.startsWith("javax.") ||
            name.startsWith("android.") ||
            name.startsWith("androidx.")
        ) {
            return emptyList()
        }
        val declaredMethods = clazz.declaredMethods
        declaredMethods.forEach {
            val annotation = it.getAnnotation(Subscribe::class.java) ?: return@forEach
            val parameterTypes = it.parameterTypes
            if (parameterTypes.size != 1) {
                throw RuntimeException("AndroidBus只能接收一个参数")
            }
            val threadModel = annotation.threadModel
            val subscribeMethod = SubscribeMethod(
                it,
                threadModel,
                parameterTypes[0]
            )
            list.add(subscribeMethod)
        }
        return list
    }

    /**
     * 发送事件
     * @param bean
     */
    fun post(bean: Any) {
        map.forEach {
            val list = it.value
            list.forEach { subscribeMethod ->
                if (subscribeMethod.eventType.isAssignableFrom(bean::class.java)) {
                    when (subscribeMethod.threadModel) {
                        ThreadModel.POSTING -> {
                            callback(subscribeMethod, it.key, bean)
                        }
                        ThreadModel.MAIN -> {
                            if (Looper.myLooper() == Looper.getMainLooper()) {
                                callback(subscribeMethod, it.key, bean)
                            } else {
                                handler.post {
                                    callback(subscribeMethod, it.key, bean)
                                }
                            }
                        }
                        ThreadModel.ASYNC -> {
                            if (Looper.myLooper() != Looper.getMainLooper()) {
                                callback(subscribeMethod, it.key, bean)
                            } else {
                                executors.execute {
                                    callback(subscribeMethod, it.key, bean)
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 回调
     * @param subscribeMethod 注册方法
     * @param subscribe 订阅类
     * @param bean 事件
     */
    private fun callback(subscribeMethod: SubscribeMethod, subscribe: Any, bean: Any) {
        val method = subscribeMethod.method
        method.invoke(subscribe, bean)
    }
}

在Activity.onCreate()中调用register()注册,onDestroy()中调用unRegister()取消注册。

定义事件订阅方法,触发事件时调用post()。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        AndroidBus.register(this)

        tvMain.setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            startActivity(intent)
        }
    }

    @Subscribe
    fun call(str: String) {
        if (str == "posting") tvMain.text = "posting"
    }

    override fun onDestroy() {
        super.onDestroy()
        AndroidBus.unRegister(this)
    }
}

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        btSecond.setOnClickListener {
            AndroidBus.post("posting")
            onBackPressed()
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读