2013-04-02 64 views
1

我們已經發布了一個基本的iOS應用程序(使用FB 4.6用Adobe Flex/AIR構建),用於新發布的軟件產品,通過對應用程序進行增強,從本質上使其功能更上一層樓。ASP.NET Web服務在Adobe Flex/AIR應用程序中導致內存泄漏

我已經做了很多改進,並取得了不同程度的成功。但是,我離題了。

我發現應用程序中似乎存在嚴重的內存泄漏,直到現在它才被發現。

該應用程序的最初版本並沒有做很多,而且對於大多數目的來說它已經足夠了。但現在它包含更多的功能,我在測試中注意到它在iPad上有點呆滯。我把它寫成設備問題,並猜測第一代iPad並不像新iPad那樣強大。

我們在同事的iPad 3上測試了該應用程序,發現了相同類型的速度問題。我通過FB的分析器運行應用程序,發現它似乎使用了大量的內存。當然,這個應用程序是針對移動平臺的,並且分析器在Windows中運行Flash Player中的應用程序,但我認爲這是問題。

出現在應用程序中的第一個視圖只是一個登錄屏幕。我看着應用程序啓動時的圖形,內存使用量徘徊在很低的水平,然後突然增加到120MB。這是沒有來自用戶的輸入。登錄或切換視圖會使用量增加一倍甚至三倍,並且永遠不會降低。我會承認,也許我對於資源的使用並不像我應該的那樣意識到,但是我一直在努力清除對象,比如我去。

大部分後端功能都是通過調用ASP.NET編寫的Web服務完成的。 Web服務使用Web服務嚮導插入到Flash Builder中...例如,URL將爲http://www.mydomain.com/MyWebService.asmx?WSDL

第一個「主頁」視圖不會調用任何Web服務功能,除非用戶實際執行了某些操作按一個按鈕。我從視圖的「fx:Declarations」部分取出了Web服務聲明,並將其中的任何引用註釋掉,然後再次嘗試了分析器。

這一次,使用限制在2MB。這是一個天文數字的差異。

分析器顯示99%的內存被「XML」類使用,這導致我認爲Web服務是問題。它幾乎看起來像視圖在啓動時查詢Web服務,並且正在使用大量內存。

我在這裏錯過了什麼嗎?有沒有更有效的方式從AIR應用程序調用Web服務?我究竟做錯了什麼?

在此先感謝!

+0

我只是編輯我的帖子...我認爲沒有網絡服務的使用是20MB,但我錯了。重新打開FB,發現它只有2MB! – CodeCanuck

+0

沒有審查您的具體代碼;很難爲您提供任何其他信息。似乎懷疑註釋掉Web服務會導致應用程序使用的內存少於未使用的內存。 – JeffryHouser

+0

您能想到Web服務會導致大量內存使用的原因嗎?地獄,我不在乎內存使用是否有點高。我想要做的就是堵塞泄漏(如果確實有泄漏),並讓用戶看到應用程序平滑流暢地切換視圖。現在,當改變視圖時,它就像瘋了一樣抖動。 – CodeCanuck

回答

1

我想我終於明白了!

這篇文章是爲其他可能遇到同樣問題的人提供的公共服務。

我不確定爲什麼Web服務會導致內存使用情況如此高峯,但我可以解決它。在我的情況下,使用率仍低於120MB,但不同之處在於,當我切換視圖時,它並不像以前那樣翻倍/三倍。

感謝艾米帶領我走向正確的方向。我基本上把所有的聲明都拿出來了,並且在Web服務中公開聲明,像這樣。

public var ws:WebService = new WebService(); 

protected function viewnavigatorapplication1_preinitializeHandler(event:FlexEvent):void 
{ 
    ws.loadWSDL("http://www.mydomain.com/MyWebService.asmx?WSDL"); 
} 
在你的意見

則...

private var serviceOperation:AbstractOperation; 
private var myToken:AsyncToken; 

private function getData():void 
{ 
    var firstName:String = "John"; 
    var lastName:String = "Smith";   

    serviceOperation = this.parentApplication.ws.getOperation("MyFunction"); 
    serviceOperation.addEventListener(FaultEvent.FAULT, fault); 
    serviceOperation.addEventListener(ResultEvent.RESULT, result); 

    myToken = serviceOperation.send(firstName, lastName); 
} 

public function result(data:Object):void 
{ 
    switch(data.token) 
    { 
     case myToken: 
      processResults(data); 
      break; 
     default: 
      break; 
    } 
} 

而且很明顯,請務必移除事件偵聽器,當你與他們完成設置你的對象引用爲null。我爲了令牌和操作做到了這一點,以確保安全。

我還沒有對內存的使用徹底測試的應用程序,但乍一看,它沒有成倍增加,我相信我甚至看到它下來時,垃圾收集踢。

+1

不知何故,您的評論回覆沒有觸發我的收件箱。我不會建議像這樣引用parentApplication。這是關注不好的分離。相反,我會從View生成一個事件來請求數據,然後公開一個公共屬性,數據在返回時可以被注入。 –