当节点数超过30000

时间:2015-11-02 06:30:48

标签: actionscript-3 flex flex4 lazy-loading flex4.5

我想以这样的方式打开Flex mx Tree的所有节点,以便UI始终响应。通常,当节点数量有限时,此代码就可以正常工作。

public function expandAllNodes():void {
  for (var i:int = 0; i < this.dataProvider.length; i++) {
    expandChildrenOf(this.dataProvider.getItemAt(i), true);
  }
}

也许我需要callLater而不是直接调用函数

public function expandAllNodes():void {
  for (var i:int = 0; i < this.dataProvider.length; i++) {
    calllater(expandChildrenOf,[this.dataProvider.getItemAt(i), true]);
  }
}

但这也不起作用。

2 个答案:

答案 0 :(得分:0)

在这种情况下,使用callLater无济于事。来自documentation

  

callLater方法将为下一次屏幕刷新而不是在当前更新中对要执行的操作进行排队。

在你的循环中使用callLater只需将所有的expandChildrenOf()调用推送到下一个屏幕刷新 - 这仍然会在单个更新周期中投入太多工作。

相反,您可以将循环扩展到多个帧并限制每帧完成的工作:

private var processingLimit:int = 10; //experiment to get a reasonable value for this
private var totalNodes:int = 0;
private var nodesProcessed:int = 0;

public function expandAllNodes():void {
    this.totalNodes = this.dataProvider.length;
    this.addEventListener(Event.ENTER_FRAME, expandNextNode);
}

private function expandNextNode(e:Event):void {
    var numToProcess = Math.min(processingLimit + nodesProcessed, totalNodes);
    for (var i:int = nodesProcessed; i < numToProcess; i++) {
        nodesProcessed++;
        expandChildrenOf(this.dataProvider.getItemAt(i), true);
    }

    if (numToProcess == totalNodes) {
        this.removeEventListener(Event.ENTER_FRAME, expandNextNode);
    }
}

n.b。确保expandChildrenOf不递归地打开子项的子项 - 如果确实如此,那么您仍然可以基于对expandChildrenOf(1);的单个调用来扩展整个树!

答案 1 :(得分:0)

这就是我解决问题的方法

private const PROCESSING_LIMIT:int = 25; 
public var _expandNodesStack:Vector.<Object>;
private function expandNextNode(e:Event):void {
  for (var i:int = 0; i < PROCESSING_LIMIT; i++) {
    var item:* = _expandNodesStack.pop();
    if (item)
      expandItem(item, true);
    else
      break;
  }
  if (_expandNodesStack.length == 0) {
    this.removeEventListener(Event.ENTER_FRAME, expandNextNode);
  }
}



public function expandAllNodes():void {
  if(this.dataProvider == null || this.dataProvider.length <= 0) return;
  if (_expandNodesStack != null && _expandNodesStack.length > 0) {
    //already expanding so abort this operation
    return;
  }
  if (_expandNodesStack == null) _expandNodesStack = new <Object>[];
  iterateAndPushToStack(this.dataProvider.getItemAt(0));
  _expandNodesStack.reverse();

  this.addEventListener(Event.ENTER_FRAME, expandNextNode);
}

private function iterateAndPushToStack(item:Object):void {
  if (iterator == null)
    return;

  // if it is not a branch item there's nothing to do
  if (item != null && item.children is ArrayCollection && item.children.length > 0) {
    _expandNodesStack.push(item);
    var childItems:ArrayCollection;
    childItems = item.children;
    if (childItems) {
      for each (var object:Object in childItems) {
        iterateAndPushToStack(object);
      }
    }
  }
}