不积跬步无以至千里,不积小流无以成江海。没有必要听到别人说什么这这那那,感觉很高大上的话题,当你基础一切扎实之后,一切都是水到渠成。
小贴士:这个是我同事写的,他看完Android分发的源码之后,手写的一个简单的库,代码很少,但是确实很巧。当时是为了解决一个什么问题呢?当一个页面有很多的EditText,当我点击提交按钮的时候需要校验,当我发送了一个事件,一旦有子View(EditText)消费了,就证明有一项校验没有通过,那么当前就不能提交,并弹出Toast,告诉用户为啥不能提交成功。有人说,我其他方式也能实现,是的,方式很多,我纠结的不是怎么实现,而是这个实现的方式很巧,把源代码用到工程。接下来,我给大家介绍一下这个简短的库。
interface IEventInterceptor {
// 根据事件ID,和具体的数据,来选择处理事件
fun handleEvent(eventId: Int, data: Any?): Boolean
}
interface IEventDispatcher : IEventInterceptor {
// 分发事件相关方法
// 正常的分发事件
fun dispatchEvent(eventId: Int, data: Any?): Boolean
// 向子View先分发事件
fun dispatchDown(eventId: Int, data: Any?): Boolean
// 子View不消费事件,自己以及兄弟节点也不消费,事件往上传递
fun dispatchUp(eventId: Int, data: Any?): Boolean
// 子View相关方法
fun addChild(eventDispatcher: IEventDispatcher)
fun removeChild(eventDispatcher: IEventDispatcher)
fun getChildren(): List<WeakReference<IEventDispatcher>>?
// 拦截器相关
fun getInterceptors(): List<WeakReference<IEventInterceptor>>?
fun addInterceptor(interceptors: IEventInterceptor)
fun removeInterceptor(interceptors: IEventInterceptor)
// 设置当前View的父View
fun setParent(parent: IEventDispatcher?)
}
class EventDispatcherImpl : IEventDispatcher {
// 父分发器
private var mDispatcherParent: IEventDispatcher? = null
// 子View分发
private val mDispatcherChildren: CopyOnWriteArrayList<WeakReference<IEventDispatcher>> by lazy {
CopyOnWriteArrayList<WeakReference<IEventDispatcher>>()
}
// 拦截器(拦截器也是有可能消费事件的,对传统的事件分发进行了扩展)
private val mInterceptors: CopyOnWriteArrayList<WeakReference<IEventInterceptor>> by lazy {
CopyOnWriteArrayList<WeakReference<IEventInterceptor>>()
}
// 当前View处理器,自己对事件的处理
private var mEvenDispatcherPoxy: IEventInterceptor
// 子View集合,用弱引用,当子View销毁之后,不用手动remove,会自动销毁,销毁之后会进到这个queue
private val childrenReferenceQueue: ReferenceQueue<IEventDispatcher> by lazy {
ReferenceQueue<IEventDispatcher>()
}
// 拦截器集合,同样弱引用,当拦截器销毁,销毁之后会进去这个queue
private val interceptorsReferenceQueue: ReferenceQueue<IEventInterceptor> by lazy {
ReferenceQueue<IEventInterceptor>()
}
constructor(eventDispatcher: IEventDispatcher) {
mEvenDispatcherPoxy = eventDispatcher
}
constructor(eventDispatcher: IEventDispatcher, parent: IEventDispatcher?) {
mEvenDispatcherPoxy = eventDispatcher
this.mDispatcherParent = parent
this.mDispatcherParent?.let { it.addChild(this) }
}
// 设置当前“View”的父亲,联系起来
override fun setParent(parent: IEventDispatcher?) {
this.mDispatcherParent = parent
this.mDispatcherParent?.let {
it.addChild(this)
}
}
// 当前View处理事件,首先拦截器处理,拦截器不处理,就自己来处理,很好理解
override fun handleEvent(eventId: Int, data: Any?): Boolean {
if (mInterceptors != null) {
cleanInterceptorsReferenceIfNeed()
for (interceptor in mInterceptors) {
val ref = interceptor.get()
val isHandled = ref?.handleEvent(eventId, data) ?: false
if (isHandled) {
return isHandled
}
}
}
return mEvenDispatcherPoxy.handleEvent(eventId, data)
}
// 这个是事件分发的入口,开始分发事件,刚开始把事件分发给孩子,孩子不处理,把事件向上分发
override fun dispatchEvent(eventId: Int, data: Any?): Boolean {
val isHandled = dispatchDown(eventId, data)
return if (isHandled) true else dispatchUp(eventId, data)
}
// 事件向下分发,发给子View
override fun dispatchDown(eventId: Int, data: Any?): Boolean {
// 判断是不是有子View销毁了,如果销毁了,就remove掉
cleanDispatcherReferenceIfNeed()
// 遍历子View,看看是不是有子View处理事件
for (item in mDispatcherChildren) {
val ref = item.get()
if (ref != null) {
val handled = ref.dispatchDown(eventId, data)
if (handled) {
return true
}
}
}
// 如果子View不处理,就自己来处理
return handleEvent(eventId, data)
}
// 分析一
// 子View和自己都不处理,事件向上抛
override fun dispatchUp(eventId: Int, data: Any?): Boolean {
val dispatcher = mDispatcherParent ?: return false
val children: List<WeakReference<IEventDispatcher>>? = dispatcher.getChildren()
// 看看当前View的兄弟节点是不是会处理事件
if (children != null) {
for (child in children) {
val ref = child.get()
if (ref != null && ref !== this && ref.dispatchDown(eventId, data)) {
return true
}
}
}
val eventInterceptors: List<WeakReference<IEventInterceptor>>? = mDispatcherParent?.getInterceptors()
// 判断父View的拦截器是不是可以处理事件
if (eventInterceptors != null) {
for (child in eventInterceptors) {
val ref = child.get()
if (ref != null && ref !== this && ref.handleEvent(eventId, data)) {
return true
}
}
}
// 当前父View是否处理事件
val handled = dispatcher.handleEvent(eventId, data)
// 当前父View处理就返回true,否则继续往上抛
return if (handled) {
true
} else dispatcher.dispatchUp(eventId, data)
}
override fun addChild(eventDispatcher: IEventDispatcher) {
if (contain<IEventDispatcher>(mDispatcherChildren, eventDispatcher) < 0) {
mDispatcherChildren.add(WeakReference<IEventDispatcher>(eventDispatcher, childrenReferenceQueue))
}
cleanDispatcherReferenceIfNeed()
}
// 移除一个子View
override fun removeChild(eventDispatcher: IEventDispatcher) {
var index: Int
if (contain<IEventDispatcher>(mDispatcherChildren, eventDispatcher).apply { index = this } >= 0) {
mDispatcherChildren.removeAt(index)
}
}
override fun getChildren(): List<WeakReference<IEventDispatcher>>? {
cleanDispatcherReferenceIfNeed()
return mDispatcherChildren
}
override fun getInterceptors(): List<WeakReference<IEventInterceptor>>? {
cleanInterceptorsReferenceIfNeed()
return mInterceptors
}
override fun addInterceptor(interceptor: IEventInterceptor) {
if (contain<IEventInterceptor>(this.mInterceptors, interceptor) < 0) {
this.mInterceptors.add(
WeakReference(interceptor, interceptorsReferenceQueue)
)
}
cleanInterceptorsReferenceIfNeed()
}
override fun removeInterceptor(interceptor: IEventInterceptor) {
var index: Int
if (contain<IEventInterceptor>(this.mInterceptors, interceptor).apply { index = this } >= 0) {
this.mInterceptors.removeAt(index)
}
}
fun getParent(): IEventDispatcher? {
return mDispatcherParent
}
private fun <T> contain(refList: List<WeakReference<T>>?, obj: T): Int {
var index = -1
if (refList.isNullOrEmpty()) {
return index
}
for (item in refList) {
index++
val ref = item.get()
if (ref != null && ref === obj) {
return index
}
}
return -1
}
// 清除销毁的子View
private fun cleanDispatcherReferenceIfNeed() {
innerCleanReferenceQueue(childrenReferenceQueue, mDispatcherChildren)
}
// 清除销毁的拦截器
private fun cleanInterceptorsReferenceIfNeed() {
innerCleanReferenceQueue(interceptorsReferenceQueue, mInterceptors)
}
private fun innerCleanReferenceQueue(referenceQueue: ReferenceQueue<*>?, targetList: MutableList<*>?) {
if (targetList == null || referenceQueue == null) {
return
}
var reference = referenceQueue.poll()
while (reference != null) {
if (targetList.contains(reference)) {
targetList.remove(reference)
}
reference = referenceQueue.poll()
}
}
}
分析一:当我看到这个方法块的时候,我比较疑惑,问了同事一个问题:为啥当前View处理不了,直接抛给他的父亲不就好了,责任链不应该就是这样的吗,为哈我还需要关注兄弟节点和父View呢?他说是为了减少复杂度,父View只管往上抛就行,也说的通吧,其实联系事件分发,也不难实现的,大家可以自己思考一下。