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");
            }
4

3 回答 3

3

当垃圾收集器找到并擦除您的孤立实例时,实际上会释放内存。在此之前,您的内存使用情况将表明内存中有一个实例。没有办法强制垃圾回收,System.gc()只调用“指示”Flash 运行它,它可能不服从。所以,你已经做了你该做的,顺其自然吧。

于 2013-01-16T11:24:48.287 回答
1

删除所有引用(包括阶段和清空对象)是释放内存所需的全部内容。

如果对象没有被释放,那么你错过了一些东西或做错了事或不按顺序。

仔细检查您的代码,确保您确定对象被引用的位置,以便您可以删除它们。

查看您的示例代码:

if(selectedArea != null) selectedArea = null;

在这里,您要确保 selectedArea 为空。但是在你再次测试 selectedArea 之后立即(你知道它是 null 所以这个块永远不会使用)

if(selectedArea != null){
//Remove the area from the container...
areaContainer.removeChild(selectedArea);
//...and nullify it.
selectedArea = null;
}
于 2013-01-16T11:13:25.220 回答
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

在大多数情况下,这就是您需要做的所有事情,您执行此操作的方式将确定对象是否被清除。考虑以下情况。

您有一个具有映射属性的自定义精灵类(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()]

好吧……呼吸……正确的方法其实很简单。

正确- 这里我们使用 [Dynamic] 对象而不是 [Static] 类对象,这被认为是对象映射:

//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)

尽管这可以完美运行……但在工作环境中并未普遍接受或建议。

于 2013-01-16T17:11:37.137 回答