论Cocos2d-x的释放资源-新闻详情

论Cocos2d-x的释放资源


发布时间:2016-08-05责任编辑:朱明 浏览:1767


有场景A跟场景B,场景A是当前场景,场景B是将要替换的新场景。那么A场景的资源释放最佳时机是在什么时候呢?

这是释放资源的代码(注意要按这个顺序释放):

1

2

3

4

CCAnimationCache::purgeSharedAnimationCache();

SpriteFrameCache::getInstance()->removeUnusedSpriteFrames();

CCTextureCache::getInstance()->removeUnusedTextures();

CCTextureCache::getInstance()->getCachedTextureInfo();

1.

最开始我想到的,应该是在场景AonExit里释放,试验了下,资源并没有被释放,说明当前纹理仍然在

被引用,即场景A的子节点并未remove

后来查了下,发现每个场景的资源释放都是在一个叫dealloc的方法里,而这个方法是在onExit之后执行的。

也就是说在onExit里释放资源是不合适的做法。

 

2.

我突然想起来,每个类不都有个析构函数么?析构函数是在该类的对象被delete时调用的,

只要在A场景的析构函数里释放不就可以了?试验了下,发现也没效果,

仔细想想,我创建场景用的方法是Cocos2DX推荐的默认方法,即场景类继承一个Layer

然后再createScene里创建一个Scene,再把当前类添加到Scene里。替换场景后,

Layer被释放时,场景中的其他资源并不一定被释放,所以此方法也是行不通的。

 

3.

竟然场景真正remove子节点是在dealloc方法里,那么在dealloc里释放资源不就好?

可惜的是我根本就找不到有这个方法。于是放弃了。

后来查了下场景的调用顺序规则:

1

2

3

4

5

6

7

replaceScene : SceneB

init : SceneB

onExitTransitionDidStart : SceneA

onExit : SceneA

dealloc : SceneA

onEnter : SceneB

onEnterTransitionDidFinish : SceneB

由此可看出,B场景的onEnter函数在A场景的dealloc之后执行。

而且那么只要在B场景的onEnter里释放A场景的资源就可以。

试验了下,资源的确被释放了。

而且,释放资源是在B场景的init之后执行,这样的好处就是,假设场景B中用到场景A中的某些资源,

这些资源就不会被释放再加载,造成不必要的内存高峰。

 

4.

问题到此结束了吗?我也以为结束了,然后又发现新问题。

一旦我给场景过渡加上效果,以上方法就不灵验了,释放失败。如下:

Director::getInstance()->replaceScene(CCTransitionFade::create(0.5f, SceneB::createScene()));

然后调试跟踪下执行顺序,发现问题所在了。

当有过渡效果存在的时候,执行顺序变成这样:

1

2

3

4

5

6

replaceScene : SceneB

init : SceneB

onExitTransitionDidStart : SceneA

onEnter : SceneB

onExit : SceneA

onEnterTransitionDidFinish : SceneB

没错,场景A并不会立刻结束,而是等到动画效果完毕后才结束。

但是我发现不管有没有使用过渡动画,最后执行的总是onEnterTransitionDidFinish

那么我们只要将资源释放放在这里就行了。

经过试验,发现又失败了。。。

为啥,因为虽然dealloc方法是在onExit之后执行,但并不是紧追其后,也就是说,

有可能在onEnterTransitionDidFinish 之前,也有可能在其后,因此我们直接在

onEnterTransitionDidFinish 里释放资源并不一定可行。那该怎么解决?

这里我使用了延时释放的方法,在onEnterTransitionDidFinish 执行后过一段时间,

再调用释放资源的方法,这样就可以确保资源被释放。

scheduleOnce(CC_SCHEDULE_SELECTOR(SceneB::release), 2.0f);

 

5.

以上方法的确是可以将资源释放掉,但是不是我们所要的最佳时机呢?

仔细观察,B场景的init是在A场景的释放之前的,也就是说,在B场景诞生,A场景彻底释放

的短时间内,会存在AB场景的所有资源共存的现在。这个时候内存达到巅峰。如果A场景

B场景的资源所占内存都非常大的时候,或许会造成崩溃。

那么我们应该如何解决?

目前我的解决方法就是在场景过渡的时候增加一个过渡场景,也就是Loading场景,Loading场景

本身所需的资源并不多,在A场景资源释放完毕后,再开启B场景的资源加载。

 

 春秋工作室    供稿