Cocos2d-x 学习笔记(7) 内存管理 Sprite SpriteFrame Texture2D

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);
posted @ 2019-07-24 14:27  deepcho  阅读(1941)  评论(0编辑  收藏  举报

博客园提供博客支持
爱我所选,选我所爱。
❤️