写这篇的出发点是因为我需要手动修改素材的像素,目前的接口要修改很容易,但是会造成内存管理,key冲突等问题,为了形成一个较优的方案,先研究下引擎自身的实现。
主要从缓存中的对象的产生->使用->回收角度来看,如果我描述的有什么问题,欢迎交流。
一、加载plist文件到内存
一般从plist加载到CCSpriteFrameCache使用该方法:void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist)
step 1.首先调用CCTexture2D * CCTextureCache::addImage(const char * path)产生CCTexture2D 对象,
step 2.调用void CCSpriteFrameCache::addSpriteFramesWithDictionary(CCDictionary* dictionary, CCTexture2D *pobTexture)方法
在这个方法中,将会产生CCSpriteFrame对象并管理起来,同时将step 1产生CCTexture2D 对象关联给CCSpriteFrame对象并retain。
此时,CCSpriteFrame对象的计数是1, CCTexture2D 计数是1+被关联次数;
二、使用Cache中的CCSpriteFrame对象
step1.我们使用CCSpriteFrame* CCSpriteFrameCache::spriteFrameByName(const char *pszName)方法从cache中获得CCSpriteFrame对象
step2.将CCSpriteFrame关联给CCAnimationFrame并retain(CCAnimationFrame析构时会调用CCSpriteFrame的release)
step3.给CCprite播放动画,动画播放过程会调用CCSprite::setDisplayFrame(CCSpriteFrame *pNewFrame),该方法会对CCTexture2D 对象retain一次,析构会release
从上分析可知:
1、使用过程中CCSpriteFrameCache中的CCSpriteFrame对象计数可能会改变,但是使用完毕后该计数会恢复,正常使用不存在外部释放资源的可能。
2、CCTextureCache的CCTexture2D 对象同上
3、两个Cache类中的资源是恒存在的,需要释放必须手动释放,否则内存占用会越来越大。
大概代码样例如下:
string pics[] = {
"66Made_JG_28_Trans_0_0.png",
"66Made_JG_28_Trans_0_1.png",
"66Made_JG_28_Trans_1_0.png",
"66Made_JG_28_Trans_1_1.png",
"66Made_JG_28_Trans_2_0.png",
"66Made_JG_28_Trans_2_1.png",
"66Made_JG_28_Trans_3_0.png",
"66Made_JG_28_Trans_3_1.png",
"66Made_JG_28_Trans_4_0.png",
"66Made_JG_28_Trans_4_1.png",
"66Made_JG_28_Trans_5_0.png",
"66Made_JG_28_Trans_5_1.png",
"66Made_JG_28_Trans_6_0.png",
"66Made_JG_28_Trans_6_1.png",
"66Made_JG_28_Trans_7_0.png",
"66Made_JG_28_Trans_7_1.png",
"66Made_JG_28_Trans_8_0.png",
"66Made_JG_28_Trans_8_1.png"};
CCArray *animateFrames = CCArray::createWithCapacity(20);
CC_RETURN_FALSE_IF(!animateFrames);
CCSpriteFrame *pFrame = NULL;
for (auto a : pics)
{
string frameName = a + D_TextureManager->getSuffix(textureInfo);
pFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(frameName.c_str());
CC_RETURN_FALSE_IF(!pFrame);
animateFrames->addObject(pFrame);
}
CCAnimation *pAnimation = CCAnimation::createWithSpriteFrames(animateFrames, 0.1f);
animateFrames->release();
CCSprite *pSprite1 = CCSprite::create();
CC_RETURN_FALSE_IF(!pSprite1);
this->addChild(pSprite1);
pSprite1->setPosition(ccp(size.width/2, size.height/2));
pSprite1->runAction(CCAnimate::create(pAnimation));
三、如何合理回收这部分资源
step1.回收CCSpriteFrameCache中的CCSpriteFrame对象:建议使用void CCSpriteFrameCache::removeSpriteFramesFromFile(const char* plist)方法回收
step2.回收CCTextureCache中的CCTexture2D 对象:建议使用void CCTextureCache::removeUnusedTextures()方法回收
注意:removeSpriteFramesFromFile会对关联的CCTexture2D 对象进行release操作,在CCSpriteFrame回收完的情况下,CCTexture2D 的计数为1。