1. 總結
Sprite和SpriteFrame和Texture2D關系緊密,三個類都繼承了Ref類。精靈有成員精靈幀和紋理,精靈幀有成員紋理。精靈幀和紋理被精靈幀引用時,引用計數增加,不再被引用時,引用計數減少。紋理被精靈幀引用時也同理。
一個紋理可以被多個精靈幀、精靈引用,一個精靈幀可以被多個精靈引用。
為什么紋理緩存容器不用CC的包裝類Map
紋理緩存和精靈幀緩存不同,紋理緩存的容器不是包裝類,即向容器中增加和刪除紋理不會改變紋理的引用計數。
紋理除異步之外不執行autorelease(),精靈和精靈幀在create()執行autorelease()。
紋理不使用autorelease(),確保了不被引用的紋理不會在每幀結束后被自動release(),而是在需要釋放的時候調用remove等方法手動執行release(),確保對內存中的紋理手動釋放。也是讓暫時沒用但以后要用的紋理留在內存中,避免以后重新新建該texture。
紋理緩存的addImage方法中,將新紋理加入到容器時,不會增加引用計數。因為在精靈的create方法中,addImage方法執行后執行setTexture方法,使得引用計數加1。
2. Sprite
Sprite成員變量包括:
Texture2D* _texture; /// Texture2D object that is used to render the sprite SpriteFrame* _spriteFrame;
create(...)
我們執行Sprite類的createxxx(...)等方法,都會新建Sprite對象,對成員變量_texture和_spriteFrame等設置默認值,再調用autorelease()方法,將Sprite對象交給內存管理池自動管理。
setTexture(Texture2D *texture)
在給精靈設置紋理時,若紋理指針為空指針,則執行以下方法嘗試從紋理緩存中獲取Key為CC_2x2_WHITE_IMAGE_KEY的紋理的指針:
_director->getTextureCache()->getTextureForKey(CC_2x2_WHITE_IMAGE_KEY);
若空白紋理不存在於紋理內存,則新建Image類對象從而新建空白紋理。Image對象繼承Ref類,新建時默認引用計數=1,在空白紋理的指針賦給紋理指針后,Image對象執行release()方法,從內存中刪除。
此時,若參數紋理指針不等於Sprite本身的紋理指針時,參數紋理retain(),本身紋理release(),參數紋理作為本身紋理指針。
setSpriteFrame(SpriteFrame *spriteFrame)
在給精靈設置精靈幀時,若參數精靈幀指針不等於本身精靈幀指針,對本身精靈幀release(),參數精靈幀retain(),參數精靈幀作為本身精靈幀。
~Sprite()
Sprite對象析構時,會對成員_spriteFrame和_texture執行release()。
addChild(...) removeChild(...) 不再贅述。
3. SpriteFrame SpriteFrameCache
精靈幀緩存的容器_spriteFrames是Map<std::string, SpriteFrame*>類型,添加精靈幀和刪除都封裝了retain()和release()方法
SpriteFrame::create(const std::string& filename, const Rect& rect)
創建精靈幀時,要將精靈幀執行autorelease()方法,放入內存管理池。
~SpriteFrame()
析構時,對精靈幀成員_texture執行release()
SpriteFrame::setTexture(Texture2D * texture)
對精靈幀的成員_texture設置新的時,原先紋理執行release(),新紋理執行retain()。
SpriteFrame::initWithTexture(Texture2D* texture, ...)
用紋理對精靈幀初始化,紋理執行retain()
SpriteFrameCache::removeSpriteFrames()
SpriteFrameCache::removeSpriteFrameByName(const std::string& name)
SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D* texture)
刪除是對Map容器執行clear(),會對容器中所有精靈幀執行release(),再清空map。刪除特定精靈幀,對容器中精靈幀release()。增加特定精靈幀,對容器中精靈幀retain()。
SpriteFrameCache::destroyInstance()
精靈幀緩存是單例,銷毀時執行release()。
4. Texture2D TextureCache
紋理緩存是對紋理的緩存,紋理指針以map形式被保存在容器_textures中,容器類型std::unordered_map<std::string, Texture2D*>。
在用Image對象創建紋理時,新建的Image對象使用完后要調用release()及時從內存中刪除。
~TextureCache()
析構時對容器中所有紋理執行release()。
addImage(const std::string &path)
在添加紋理到紋理緩存中,如果紋理不存在於緩存,且又新建該紋理失敗,就把剛剛new的texture對象release()。
image = new (std::nothrow) Image();
texture = new (std::nothrow) Texture2D(); if (texture && texture->initWithImage(image)) { // ... } else { // ... CC_SAFE_RELEASE(texture); texture = nullptr; }
CC_SAFE_RELEASE(image);
removeAllTextures()
刪除緩存容器中所有紋理,實際上是對這些紋理執行release()。
removeUnusedTextures()
刪除沒有使用的紋理,實際是對引用計數為1的紋理-1。
removeTexture(Texture2D* texture) removeTextureForKey(...)
it->second->release();
it = _textures.erase(it);