2012-07-04 62 views
0

我有以下代码:有效的方式来更新的XMLListCollection

private var xmlC:XMLListCollection = new XMLListCollection(); 
private var httpS:HTTPService = new HTTPService(); 
private var timer:Timer = new Timer(1000); 
private var xmlData:XML; 
private var xmlDataList:XMLList; 

protected function application1_creationCompleteHandler(event:FlexEvent):void 
{ 
    httpS.url = "data.xml"; 
    httpS.addEventListener(ResultEvent.RESULT, resultHTTP); 
    httpS.resultFormat="e4x"; 
    httpS.send(); 

    timer.start(); 
    timer.addEventListener(TimerEvent.TIMER, updateXMLC); 
} 

private function updateXMLC(event:TimerEvent):void 
{ 
    xmlC.source = xmlDataList; 
    httpS.send(); 
} 

private function resultHTTP(event:ResultEvent):void 
{ 
    xmlData = event.result as XML; 
    xmlDataList = xmlData.dg.rows.row; 
} 

“data.xml中”有5000行,所以我需要在必要时清理它的踪迹。我有,我发现多亏了分析

  1. 每次httpS.send()被调用的方法updateXMLC两个问题,它调用的URLLoader内部这使是不需要再徘徊在内存中的XML,而不被当作垃圾收集
  2. 有更新XMLC,每当的XMLListCollection更新更有效的方式,似乎的XMLListCollection的前值不会被垃圾回收
+0

我不清楚你想问什么问题。您不会创建新的XMLListCollection;你只是重复使用相同的变量。不知道如何使用或引用XMLListCollection中的数据,就不可能确定为什么它不会被垃圾收集。 – JeffryHouser

+0

这就是完整的代码,当更改XMLListCollection的源代码时,似乎有些监听器使用了XMLNotifier.getInstance()。watchXML,我认为这可能导致内存泄漏 – Mansuro

+0

您没有提供可运行代码片段,这导致我得出的结论是必须有更多的代码。 – JeffryHouser

回答

0

如果我正确您正在恢复理解你的代码你来自SWF文件所在文件夹中的XML数据。如果是这种情况,那么最可能发生的情况是XML文件正在缓存在浏览器中,并且一次又一次地返回相同的缓存版本。

处理这些问题时,您可以添加一个虚拟URL变量,使浏览器认为您正在检索的文件是新的,并强制它再次恢复该文件。

你可以做这样的事情做到这一点:

httpS.url = "data.xml?random="+Math.floor(Math.random()*1000);

如果不能解决这个问题,那么也许它可以关联到不进行重置持有实际的XML数据的变量。您可以通过您的变量的新实例重置做到这一点:

xmlData = new XML(); 
xmlDataList = new XMLList(); 
xmlC = new XMLListCollection(); 

或者,如果你想要的是简单的复位,你可以尝试使用“刷新()”包含在Flex中所有列出方法的XMLListCollection 。

重要注意事项:如果您使用任何这些变量进行数据绑定,这可能会导致Flex无法收集数据,因为它正在某处使用。

+0

我已经通过使用每次更改的变量nocache =来使用URL技巧。我正在使用xmllist作为数据绑定的数据绑定作为datagrid的数据提供者,它将其更改为set dataprovider中的xmllistcollection – Mansuro

0

请求,接收和处理XML需要多长时间?这听起来像是一个相当大的文件,所以如果超过一秒钟,您将同时发生多个对HTTPService的调用(据我所知,您当前的计时器将尝试每秒触发一次请求,无论是否最后一个已经返回)。

我不确定这是你想要的,但我怀疑它。如果我是对的,并且只有在收到来自最后一个响应的请求后才发送请求,那么您最好是摆脱计时器及其函数,然后将resultHTTP方法更改为类似的方法这样的:

private function resultHTTP(event:ResultEvent):void 
{ 
    xmlData = event.result as XML; 
    xmlC.source = xmlData.dg.rows.row; 
    httpS.send(); 
} 

当然,你可以把它放到一个延迟它每次开机:

 
    protected function application1_creationCompleteHandler(event:FlexEvent):void 
    { 
     httpS.url = "data.xml"; 
     httpS.addEventListener(ResultEvent.RESULT, resultHTTP); 
     httpS.resultFormat="e4x"; 

     timer.start(); 
     timer.addEventListener(TimerEvent.TIMER, updateXMLC); 
    } 

    private function updateXMLC(event:TimerEvent):void 
    { 
     timer.stop(); 
     httpS.send(); 
    } 

    private function resultHTTP(event:ResultEvent):void 
    { 
     xmlData = event.result as XML; 
     xmlC.source = xmlData.dg.rows.row; 
     timer.start(); 
    } 

很抱歉,如果我误解了,虽然这个问题...

无论是方式,你可能想要把某种错误的HTTP函数n,因此它也会重新启动定时器(或者做任何你需要做的事)来处理HTTP错误。

+0

我面临的问题是当我配置文件时,当我检查未被垃圾收集的游荡对象时,我发现存在对URLLoader.toString()方法的内部调用。这个调用在返回结果时完成,它将返回的XML转换为一个字符串<这会每次都将XML保存在内存中,我不知道如何去除它。 – Mansuro

+0

是的,我只是想知道是否垃圾收集没有发生,因为可能重叠/并发呼叫。这不太可能,但奇怪的是它甚至在执行URLLoader.toString(),所以垃圾收集的方式和原因可能也很奇怪。什么时候它做URLLoader.toString()?如果您删除或修改了方法中的任何代码,它会这样做吗? – Marc

+0

另外,为什么你甚至使用这两个单独的变量数据?为什么不直接存储在'xmlC'(有点像我的例子),并完全摆脱'xmlDataList'? – Marc

4

我看了代码后会怀疑存在任何内存泄漏,因此我对自己的代码进行了测试。

您发布的代码实际上无法运行。我只是说的最少要跑它像应用标签和import语句(和反标签看到一个http服务周期完成时):

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="application1_creationCompleteHandler(event)"> 
<mx:Script> 
    <![CDATA[ 
     import mx.rpc.http.HTTPService; 
     import mx.collections.XMLListCollection; 
     import mx.rpc.events.ResultEvent; 
     import mx.events.FlexEvent; 

     private var xmlC:XMLListCollection = new XMLListCollection(); 
     private var httpS:HTTPService = new HTTPService(); 
     private var timer:Timer = new Timer(1000); 
     private var xmlData:XML; 
     private var xmlDataList:XMLList; 

     protected function application1_creationCompleteHandler(event:FlexEvent):void 
     { 
      httpS.url = "data.xml"; 
      httpS.addEventListener(ResultEvent.RESULT, resultHTTP); 
      httpS.resultFormat="e4x"; 
      httpS.send(); 

      timer.start(); 
      timer.addEventListener(TimerEvent.TIMER, updateXMLC); 
     } 

     private function updateXMLC(event:TimerEvent):void 
     { 
      xmlC.source = xmlDataList; 
      httpS.send(); 
     } 

     private function resultHTTP(event:ResultEvent):void 
     { 
      counter.text = Number(parseInt(counter.text,10)+1).toString(); 
      xmlData = event.result as XML; 
      xmlDataList = xmlData.dg.rows.row; 
     } 
    ]]> 
</mx:Script> 
<mx:Label id="counter" text="0" horizontalCenter="0" verticalCenter="0" fontSize="72"/> 
</mx:Application> 

好消息是不会有任何内存泄漏你的代码。 Profiler中也没有任何游荡物体。

坏消息是你在你的应用程序中做了什么(代码不在这里发布,因为什么原因省略) - 这是你有泄漏/游荡物体的地方。

您可以在附加代码的分析器中看到自己,http服务的前几个周期后内存不会增加。即它不会持续地抓住更多的记忆。 (顺便说一句,我拉入的XML文件大约有8000行,超过1MB)。

如果你想发布更多的代码,高兴看得更远 - 但认为这现在解决了这个谜。 ;)

这里是为了什么你做一些修正:

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="application1_creationCompleteHandler(event)"> 
<mx:Script> 
    <![CDATA[ 
     import mx.rpc.http.HTTPService; 
     import mx.collections.XMLListCollection; 
     import mx.rpc.events.ResultEvent; 
     import mx.events.FlexEvent; 

     [Bindable] private var xmlC:XMLListCollection = new XMLListCollection(); 
     private var httpS:HTTPService = new HTTPService(); 
     private var timer:Timer = new Timer(1000); 
     private var xmlData:XML; 
     private var xmlDataList:XMLList; 
     private var serviceRunning : Boolean = false; 
     private var currentData : String = ''; 

     protected function application1_creationCompleteHandler(event:FlexEvent):void 
     { 
      httpS.url = "data.xml"; 
      httpS.addEventListener(ResultEvent.RESULT, resultHTTP); 
      httpS.resultFormat="e4x"; 
      httpS.send(); 

      timer.start(); 
      timer.addEventListener(TimerEvent.TIMER, updateXMLC); 
     } 

     private function updateXMLC(event:TimerEvent):void 
     { 
      xmlC.source = xmlDataList; 
      if(!serviceRunning){ // don't call for more data until 
       httpS.send();  // you've gotten back last call 
      } 
     } 

     private function resultHTTP(event:ResultEvent):void 
     { 
      // make sure we have differences before rebinding 
      var newData : String = event.result as String; 
      serviceRunning = false; 
      counter.text = Number(parseInt(counter.text,10)+1).toString(); 
      if(newData != currentData){ 
       xmlData = event.result as XML; 
       currentData = newData; 
       xmlDataList = xmlData.dg.rows.row; 
      } 
     } 
    ]]> 
</mx:Script> 
<mx:Label id="counter" text="0" horizontalCenter="0" verticalCenter="0" fontSize="72"/> 
</mx:Application> 
+0

在原始代码中,存在导致问题的数据绑定。与每个httpservice调用一起返回的xmllist被设置为datagrid的数据提供者,该datagrid在DataGrid中转换为XMLListCollection。这就是为什么我正在寻找更好的方法来更新xmllistcollection并将其直接用作数据提供者 – Mansuro

+0

如果您可以提供代码,那么我可以看到发生了什么。现在你只是在事实之后给出提示。如果你需要帮助解决它,请通过发布代码来提供帮助。 – Nate

+0

我添加了一个数据网格到示例并绑定了集合。仍然没有内存泄漏。但是,您可能会遇到的主要问题是1)将大量数据绑定到数据网格非常密集。使用绑定不是问题,因为你没有明显的原因经常这样做是一个问题。 2)由于绑定非常密集,最终会随着时间的推移而发送多个发送呼叫。这相当于一个缓慢而令人沮丧的用户体验。我将编辑并为这些问题添加修补程序。 – Nate

相关问题