2013-01-16 50 views
0

我有一個用於刪除實例並將其替換爲另一個實例的函數的問題。基本上,它保存在內存中的項目,無論如何。在對象內部,我有弱聽者,並且在它被移除後我將所有內容都清空,但是我運行的函數檢查它是否仍然活動,告訴我它(僅僅是一個Event.ENTER_FRAME跟蹤一些帶有弱鏈接的文本)。這是一個刪除實例的功能,將其從階段中刪除並將其刪除,但它不會將其從內存中刪除

即使當我從我加載的實例中刪除所有內容時,它仍然似乎留在內存中,根據我的蹤跡它仍然是。如何從內存中徹底刪除某些東西,而不是將它從舞臺上刪除後將其全部刪除?我沒看到什麼嗎?

這是函數:

private function loadArea(inputArea:String) 
      {      
        //This is for a checker to make sure that areas only get loaded once. 
        currentRoom = inputArea; 

        //If the area currently loaded is not null, make it null now. 
        if(selectedArea != null) selectedArea = null; 

        //Null any data inside of the reference used to create the name of the new area. 
        areaReference = null; 
        //Grab the class using the input. 
        areaReference = getDefinitionByName(inputArea + "Area") as Class; 

        //Null the sprite used to house the class 
        areaSprite = null; 
        //Set the holder as a new instance of the desired class. 
        areaSprite = new areaReference() as Sprite; 

        //If the selected area is still not null for some reason, 
        if(selectedArea != null) 
        { 
          //Remove the area from the container... 
          areaContainer.removeChild(selectedArea); 
          //...and nullify it. 
          selectedArea = null; 
        } 

        //Set the current area as the newly created instance. 
        selectedArea = areaSprite; 

        //If the area is not the "Game", load in the assets one way,     
        if(inputArea != "Game") selectedArea.construct(areaAssets); 
        //otherwise do it another way. 
        else selectedArea.construct(newScreenData,apiServer,cdnServer,areaAssets); 

        //This is for a checker that fades out the screen, which it needs to fade back in soon. 
        newScreenData = null; 

        //While the container for areas has any areas inside of it, remove them. 
        while(areaContainer.numChildren) areaContainer.removeChildAt(0); 

        //...then add the new instance area to the container. 
        areaContainer.addChild(selectedArea); 

        //...then let all the parts of the game know that a new area has been laoded in. 
        Global.echoEvent.echo("gameBootUp","playAreaIn"); 
      } 

回答

1

卸下的所有參考文獻,包括階段和置零的對象是所有需要以釋放內存。

如果該對象沒有被釋放,那麼你錯過了某些東西或者做了不正確的或不按順序的事情。

仔細檢查您的代碼,確保您確定了引用對象的位置,以便將其刪除。

看你的示例代碼:

if(selectedArea != null) selectedArea = null; 

在這裏,你正在確保selectedArea爲空。 但後立即再次測試selectedArea (你知道它是空,因此從未使用過該塊)

if(selectedArea != null){ 
//Remove the area from the container... 
areaContainer.removeChild(selectedArea); 
//...and nullify it. 
selectedArea = null; 
} 
+0

是否引用了全局的東西將它保存在內存中?我有一個全局變量用於派發DataEvents發送字符串。我從實例內部添加一個事件監聽器,因此它可以從其他實例接收事件。我雖然刪除了監聽器,但我不確定是否還有其他問題繞着我可能還不知道的全局變量出現問題? –

3

內存實際上是釋放時垃圾收集器會發現和消除你的一個孤立的實例。在此之前,您的內存使用情況將顯示內存中有一個實例。沒有辦法強制垃圾收集,只調用System.gc()「指示」Flash運行它,它可能不服從。所以,你已經做了你所要做的,讓它成爲現實。

+0

'System.gc()'無論如何都只能在調試模式下工作(除非這是一個AIR應用程序)。無論如何,垃圾收集是半智能的。在實際需要對象佔用的內存之前,它不會從內存中刪除任何對象。 –

0

在每種語言中,它都非常難以「清除」內存甚至是HTML。這就是說...嘗試減少你的內存佔用。

Correct Null: 
1. remove all event listeners 
2. remove all children 
3. remove all mapped/referenced methods/parameters 
4. set the class object to null 

在大多數情況下,這是你需要做的全部事情,你這樣做的方式將決定對象是否被清除。考慮以下情況。

您有一個具有映射屬性的自定義sprite類(MEMORY FOOTPRINT#1)(映射在一個類對象引用另一個時發生)。一旦你映射/引用一個對象到另一個= MEMORY FOOTPRINT#2。添加事件= MEMORY FOOTPRINT#3等等。

定製雪碧

import flash.display.Sprite; 

class CustomSprite extends Sprite{ 

    private var _mappedProperty:Object; 

    public function addMapping(map:Object):void{ 
     _mappedProperty = map; 
    } 

    public function finalize():void{ 
     _mappedProperty = null; 
    } 
} 

假設我們在許多其他方法使用的CustomSprite,讓我們看看去除ojbect的一些常用方法。

不正確 - 在這種情況下[objToRemove]沒有設置爲null以釋放內存:

var objToRemove:CustomSprite = new CustomSprite; 

function doSomething(referenceObj:CustomSprite):void{ 

    var methodObj:CustomSprite = referenceObj; 

    //CRAZY LINES OF CODE 

    methodObj = null;  //frees memory from [doSomething::methodObj] 
    referenceObj = null; //frees memory from [doSomething::referenceObj] 

    //objToRemove is not cleared and will remain in memory 
} 

不正確 - 在這種情況下[objToRemove]有一個參考對象,因此它會不乾淨直到刪除參考文件:

var objToRemove:CustomSprite = new CustomSprite; 
var mappedObject:Sprite = new Sprite; 

objToRemove.addMapping(mappedObject);  
objToRemove.addEventListener(Event.ENTER_FRAME,onEnterFrame); 

//CRAZY LINES OF CODE 

//remove all children 
while(objToRemove.numChildren > 0){ 
    objToRemove.removeChildAt(0); 
} 

//remove all event listeners 
objToRemove.removeEventListener(Event.ENTER_FRAME,onEnterFrame); 

//this will NOT work 
objToRemove = null; 

//reason is objToRemove has a reference object of [mappedObject] 
//[mappedObject] is not a child so it needs to be removed manually 
//from WHITIN the CustomSprite class using [CustomSprite::finalize()] 

好的......呼吸......正確的方法其實很簡單。

正確 - 在這裏我們使用[動態]對象,而不是[靜態]類對象,這被認爲是對象映射:

//think of this as a global list of objects 
var objPool:Dictionary = new Dictionary; 

//create a pool reference 
objPool['poolObj'] = new CustomSprite; 

//CRAZY LINES OF CODE; 

//do the normal [null] process 

//both of these will work 
objPool['poolObj'] = null; 
//or 
delete objPool['poolObj']; 

非常高級的正確 - 沒有提供例子,我有回去工作笑...

1. Take a ByteArray clone of the class 
2. User a Loader to construct the ByteArray as the class, rather than using "new" 
3. When finished... unload/remove the loader 
4. EVERYTHING will clear... thats how a Loader works! 
(Not getting into why and how... too long of an explanation) 

雖然這完美的作品...它不是普遍接受或在工作環境中建議。

+0

感謝您的意見。我從來不知道如何在我的代碼後正確清理。我將不得不在實驗中嘗試最後一個建議,以充分理解它,但是我希望能夠自由地知道它在我想要的時候全部消失了。謝謝你回答我的問題! –

+0

沒問題...超級先進的解決方案是經過多年的Flash工作。還有其他幾種方式可以完成所提到的內容,但這些應該會給你一個好的開始。 –

相關問題