抱歉来晚了,之前版本比较急,做demo时发现仅仅是生成大量带 touch linstener的节点无法复现卡顿的情况,于是临时去掉了屏幕常亮功能来降低这个bug的发生率,中间项目事情比较多这个问题就暂时搁置下来,但是还是会有不少人遇到这个问题。
今天晚上终于闲下来,感觉复现太瞎子摸象,于是仔细分析源码后得到了结论,进而问题得到了解决
这个问题发生的原因是node 改变zIndex 时 会调用_onSiblingIndexChanged, 继而把该节点的所有兄弟节点做污染标记
_onSiblingIndexChanged () {
// update rendering scene graph, sort them by arrivalOrder
var parent = this._parent;
var siblings = parent._children;
var i = 0, len = siblings.length, sibling;
for (; i < len; i++) {
sibling = siblings[i];
sibling._updateOrderOfArrival();
eventManager._setDirtyForNode(sibling);
}
parent._delaySort();
},
问题在于 CCEventManager 的 _setDirtyForNode 方法 :
if (this._nodeListenersMap[node._id] !== undefined) {
this._dirtyNodes.push(node);
}
会把所有带监听事件的节点都加入_dirtyNodes ,而没有考虑重复问题,那么当场景里有比较多事件监听节点,并且他们不断发生zIndex变化时,可怕的事情就发生了,_dirtyNodes会被无限膨胀
于是在用户点击时 _updateDirtyFlagForSceneGraph 里会去遍历_dirtyNodes,因而引发了性能瓶颈。
我解决的办法是加入一个_dirtyNodeMap 相同node._id的节点只入数组一次,从而解决了这个问题
经过多次测试,发现问题已经得到了解决