Använd objektpooler när det är möjligt.
Ytterligare en viktig optimeringsteknik kallas objektpooler där objekt återanvänds över tiden. Du kan skapa ett definierat antal objekt när du initierar programmet och spara dem i en pool, som exempelvis i ett Array- eller ett Vector-objekt. När du är klar med ett objekt inaktiverar du det så att det inte förbrukar några processorresurser och tar bort alla gemensamma referenser. Du ska emellertid inte ange att referensen ska vara
null
för objektet eftersom det då kan omfattas av skräpinsamlingen. Du återplacerar helt enkelt objektet i poolen och hämtar det när du behöver ett nytt objekt.
Genom att återanvända objekt minskar du behovet av att skapa instanser av objekt, vilket kan vara kapacitetskrävande. Dessutom minskas chanserna att skräpinsamlingen körs, vilket kan medföra att programmet körs långsammare. Med följande kod exemplifieras objektpoolstekniken:
package
{
import flash.display.Sprite;
public final class SpritePool
{
private static var MAX_VALUE:uint;
private static var GROWTH_VALUE:uint;
private static var counter:uint;
private static var pool:Vector.<Sprite>;
private static var currentSprite:Sprite;
public static function initialize( maxPoolSize:uint, growthValue:uint ):void
{
MAX_VALUE = maxPoolSize;
GROWTH_VALUE = growthValue;
counter = maxPoolSize;
var i:uint = maxPoolSize;
pool = new Vector.<Sprite>(MAX_VALUE);
while( --i > -1 )
pool[i] = new Sprite();
}
public static function getSprite():Sprite
{
if ( counter > 0 )
return currentSprite = pool[--counter];
var i:uint = GROWTH_VALUE;
while( --i > -1 )
pool.unshift ( new Sprite() );
counter = GROWTH_VALUE;
return getSprite();
}
public static function disposeSprite(disposedSprite:Sprite):void
{
pool[counter++] = disposedSprite;
}
}
}
I SpritePool-klassen skapas en pool med nya objekt när programmen initieras. Metoden
getSprite()
returnerar instanser av dessa objekt och metoden
disposeSprite()
frisläpper dem. Koden medger att poolen växer vid behov. Det är dessutom möjligt att skapa en pool med fast storlek där nya objekt inte tilldelas när poolen är full. Försök om möjligt att skapa nya objekt i slingor. Mer information finns i
Frigöra minne
. I följande kod används klassen SpritePool för att hämta nya instanser:
const MAX_SPRITES:uint = 100;
const GROWTH_VALUE:uint = MAX_SPRITES >> 1;
const MAX_NUM:uint = 10;
SpritePool.initialize ( MAX_SPRITES, GROWTH_VALUE );
var currentSprite:Sprite;
var container:Sprite = SpritePool.getSprite();
addChild ( container );
for ( var i:int = 0; i< MAX_NUM; i++ )
{
for ( var j:int = 0; j< MAX_NUM; j++ )
{
currentSprite = SpritePool.getSprite();
currentSprite.graphics.beginFill ( 0x990000 );
currentSprite.graphics.drawCircle ( 10, 10, 10 );
currentSprite.x = j * (currentSprite.width + 5);
currentSprite.y = i * (currentSprite.width + 5);
container.addChild ( currentSprite );
}
}
Med följande kod tas alla visningsobjekt bort från visningslistan när någon klickar med musen och återanvänder dem senare i en annan åtgärd:
stage.addEventListener ( MouseEvent.CLICK, removeDots );
function removeDots ( e:MouseEvent ):void
{
while (container.numChildren > 0 )
SpritePool.disposeSprite (container.removeChildAt(0) as Sprite );
}
Obs!
Poolvektorn refererar alltid till Sprite-objekten. Om du vill ta bort objektet fullständigt från minnet behöver du en
dispose()
-metod i SpritePool-klassen, vilken tar bort alla återstående referenser.