W miarę możliwości należy zawsze umieszczać obiekty w puli.
Inną istotną metodą optymalizacji jest umieszczanie obiektów w puli, co polega na ponownym wykorzystaniu tych samych obiektów w miarę upływu czasu. Należy utworzyć określoną liczbę obiektów podczas inicjowania aplikacji, a następnie zapisać je w puli, która będzie obiektem klasy Array lub Vector. Po zakończeniu pracy z obiektem należy go dezaktywować, dzięki czemu nie będzie on zużywał zasobów procesora, a także usunąć wszystkie odwołania wzajemne. Nie należy jednak ustawiać odwołań na
null
, ponieważ mogłoby to zakwalifikować obiekt do usunięcia w procesie czyszczenia pamięci. Wystarczy umieścić obiekt z powrotem w puli, a następnie pobrać go, gdy potrzebny będzie nowy obiekt.
Ponowne korzystanie z obiektów ogranicza potrzebę tworzenia instancji obiektów, co może być kosztowne. Ponadto ogranicza prawdopodobieństwo uruchomienia procesu czyszczenia pamięci, który może znacznie spowolnić aplikację. Poniższy kod prezentuje technikę umieszczania obiektów w puli.
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;
}
}
}
Klasa SpritePool tworzy pulę nowych obiektów podczas inicjowania aplikacji. Metoda
getSprite()
zwraca instancje tych obiektów, a metoda
disposeSprite()
zwalnia je. Kod umożliwia powiększanie puli, gdy jej pojemność zostanie całkowicie wykorzystana. Możliwe jest także utworzenie puli o stałej wielkości — w takim przypadku całkowite wykorzystanie puli uniemożliwi dodawanie do niej nowych obiektów. W miarę możliwości należy unikać tworzenia nowych obiektów w pętlach. Więcej informacji zawiera sekcja
Zwalnianie pamięci
. W poniższym kodzie wykorzystano klasę SpritePool do pobierania nowych instancji:
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 );
}
}
Poniższy kod po kliknięciu przycisku myszy usuwa wszystkie obiekty wyświetlane z listy wyświetlania, a następnie wykorzystuje je ponownie dla innego zadania:
stage.addEventListener ( MouseEvent.CLICK, removeDots );
function removeDots ( e:MouseEvent ):void
{
while (container.numChildren > 0 )
SpritePool.disposeSprite (container.removeChildAt(0) as Sprite );
}
Uwaga:
Wektor puli zawsze odwołuje się do obiektów Sprite. Jeśli konieczne jest całkowite usunięcie obiektu z pamięci, wymagane jest użycie metody
dispose()
klasy SpritePool, która powoduje usunięcie wszystkich pozostałych odwołań.