TouchTarget理解

601 阅读2分钟

touchtarget概述:

Touchtarget是viewgroup的静态内部类,主要用来存储消费了事件的子view。它的数据结构是单链表型的,持有child(消费事件的子view),pointerIDbits(child子view接收的触摸点ID的集合),next(touchtarget类型,指向下一个节点)。viewgroup中存在一个touchtarget类型的成员变量mfirsttouchtarget,它持有touchtarget并且是touchtarget这个单链表的头节点,可以用来操作这个单链表。

为什么需要用touchtarget:

在view的事件分发中,如果父view没有拦截事件,那么会调用dispatchtouchevent来进行分发,在viewgroup的dispatchtouchevent中会进行循环遍历子view,来查看子view是否消费事件。我们知道一个事件序列包含actiondown,actionmove(若干个),actionup,actioncancel,如果涉及多指操作actionpointerdown和actionpointerup。这么多事件,如果每一个事件到来都遍历子view那么效率是很低的,因此引入了touchtarget单链表数据结构来存储消费了actiondown事件的子view,当该序列其他事件分发的时候会根据这个touchtarget直接找到消费事件的子view省去了后续的子view遍历询问。

为什么需要单链表结构来存储消费事件的子view:

view事件分发一个事件序列为actiondown,actionmove(若干个),actionup,actioncancel,如果涉及多指操作actionpointerdown和actionpointerup,那么可能存在多个view同时响应,同时消费某一事件序列,此时只用一个touchtarget存储显然不够的。 a.当触摸点1,产生actiondown事件,落在子view A上,则会创建一个touchtarget,并保存view A; b.触摸点2产生一个事件actionpointerdown事件,如果触摸点2也落在view A上,此时可以复用touchtarget,并给它添加触摸点2的ID; c.如果触摸点3产生一个actionpointerdown事件,并落在view B上,那么会重新创建一个touchtarget,将新的touchtarget置于头节点并指向原来的头节点,此时viewgroup中包含一个touchtarget链表(两个touchtarget对象),mfirsttouchtarget为新的头节点。

应用在使用过程中存在非常多的事件,为了提高效率节省内存开支,在touchtarget类中,存在obtain()和recyle()方法,用来管理touchtarget的创建和回收,而touchtarget的构造方法是私有的。

pointerIDbits是如何存储某一子view上触摸点ID的:

pointerIDbits是32位int型的,默认为0,每一位存在01两种。触摸点1进来,将pointeridbits最后一位置1,其它位不变;触摸点2进来,将末第二位置1,其他位不变;....依次类推最多可存储32个触摸点。其具体实现为:触摸点n进来(n为0-31之间,共32位),将1左移n为,然后再与pointerIDbits做按位或操作(|),结果赋给pointerIDbits。