COCOS2D 释放资源的最佳时机
有场景A跟场景B,
场景A是当前场景,场景B是将要替换的新场景。
那么A场景的资源释放最佳时机是在什么时候呢?
这是释放资源的代码(注意要按这个顺序释放):
|
1
2
3
4
|
CCAnimationCache::purgeSharedAnimationCache();SpriteFrameCache::getInstance()->removeUnusedSpriteFrame();CCTextureCache::getInstance()->removeUnusedTextures();CCTextureCache::getInstance()->getCachedTextureInfo(); |
1.
最开始我想到的,应该是在场景A的onExit里释放,试验了下,资源并没有被释放,说明当前纹理仍然在
被引用,即场景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 : SceneBinit : SceneBonExitTransitionDidStart : SceneAonExit : SceneAdealloc : SceneAonEnter : SceneBonEnterTransitionDidFinish : SceneB |
由此可看出,B场景的onEnter函数在A场景的dealloc之后执行。
而且
那么只要在B场景的onEnter里释放A场景的资源就可以。
试验了下,资源的确被释放了。
而且,释放资源是在B场景的init之后执行,这样的好处就是,假设场景B中用到场景A中的某些资源,
这些资源就不会被释放再加载,造成不必要的内存高峰。
4.
问题到此结束了吗?我也以为结束了,然后又发现新问题。
一旦我给场景过渡加上效果,以上方法就不灵验了,释放失败。
|
1
|
Director::getInstance()->replaceScene(CCTransitionFade::create(0.5f, SceneB::createScene())); |
然后调试跟踪下执行顺序,发现问题所在了。
当有过渡效果存在的时候,执行顺序变成这样:
|
1
2
3
4
5
6
|
replaceScene : SceneBinit : SceneBonExitTransitionDidStart : SceneAonEnter : SceneBonExit : SceneAonEnterTransitionDidFinish : SceneB |
没错,场景A并不会立刻结束,而是等到动画效果完毕后才结束。
但是我发现不管有没有使用过渡动画,最后执行的总是onEnterTransitionDidFinish,
那么我们只要将资源释放放在这里就行了。
经过试验,发现又失败了。。。
为啥,因为虽然dealloc方法是在onExit之后执行,但并不是紧追其后,也就是说,
有可能在onEnterTransitionDidFinish 之前,也有可能在其后,因此我们直接在
onEnterTransitionDidFinish 里释放资源并不一定可行。那该怎么解决?
这里我使用了延时释放的方法,在onEnterTransitionDidFinish 执行后过一段时间,
再调用释放资源的方法,这样就可以确保资源被释放。
|
1
|
scheduleOnce(CC_SCHEDULE_SELECTOR(SceneB::release), 2.0f); |
5.
以上方法的确是可以将资源释放掉,但是不是我们所要的”最佳时机”呢?
仔细观察,B场景的init是在A场景的释放之前的,也就是说,在B场景诞生,A场景彻底释放
的短时间内,会存在A,B场景的所有资源共存的现在。这个时候内存达到巅峰。如果A场景
跟B场景的资源所占内存都非常大的时候,或许会造成崩溃。
那么我们应该如何解决?
目前我的解决方法就是在场景过渡的时候增加一个过渡场景,也就是Loading场景,Loading场景
本身所需的资源并不多,在A场景资源释放完毕后,再开启B场景的资源加载。
COCOS2D 释放资源的最佳时机的更多相关文章
- cocos2d源码剖析
1. TextureAtlas http://www.cocoachina.com/bbs/read.php?tid-311439-keyword-TextureAtlas.html 2. Label ...
- cocos2D(三)---- 第一cocos2d的程序代码分析
在第一讲中已经新建了第一个cocos2d程序,执行效果例如以下: 在这讲中我们来分析下里面的代码,了解cocos2d的工作原理,看看屏幕上的这个"Hello World"是怎样显示 ...
- 三、第一个cocos2d程序的代码分析
http://blog.csdn.net/q199109106q/article/details/8591706 在第一讲中已经新建了第一个cocos2d程序,运行效果如下: 在这讲中我们来分析下里面 ...
- 小尝试一下 cocos2d
好奇 cocos2d 到底是怎样一个框架,正好有个项目需要一个游戏框架,所以稍微了解了一下.小结一下了解到的情况. 基本概念 首先呢,因为 cocos2d 是基于 pyglet 做的,你完全可以直接用 ...
- 采用cocos2d-x lua 制作数字滚动效果样例
require "Cocos2d"require "Cocos2dConstants"local testscene = class("testsce ...
- Cocos2d 利用继承Draw方法制作可显示三维数据(宠物三维等)的三角形显示面板
很久没有写博客了,这段时间比较忙,又是搬家又是做自己的项目,还有太多琐碎的事情缠身,好不容易抽出时间把最近自己做的一些简单例子记录一下. 在我的项目中,我需要一个显示面板来显示游戏中的一个三维数据,例 ...
- iPhone开发与cocos2d 经验谈
转CSDN jilongliang : 首先,对于一个完全没有mac开发经验,甚至从没摸过苹果系统的开发人员来说,首先就是要熟悉apple的那一套开发框架(含开发环境IDE.开发框架uikit,还有开 ...
- using 释放资源
我们知道使用C#程序访问数据库资源需要几个步骤:创建连接,打开连接,访问数据库,关闭连接,基本架构如下: SqlConnection conn = new SqlConnection(connStri ...
- cocos2d学习记录
视频 - http://www.manew.com/forum-105-3.html一个论坛帖 - http://www.zhihu.com/question/21114802官网 - http:// ...
随机推荐
- Android成长日记-使用ViewFlipper实现屏幕切换动画效果
(一) ViewFlipper介绍 Android系统自带的一个多页面管理控件,它可以实现子界面的自动切换 (二) 为ViewFlipper加入View 1. 静态导入:在Layout布局文件中直接导 ...
- POJ 2457 Part Acquisition
第一反应是BFS,比较直观,但是输出路径写的不是很熟练,此外,习惯不好,“==”写成了“=”,所以常量一定放前面! #include <cstdio> #include <queue ...
- TypeScript Interface(接口)
类型检查专注于解析值所具有的"形态",这是TypeScript的核心原则之一.这个有时候被称为"duck typing"或者"structural s ...
- 解决Eclipse 项目报错:Unbound classpath container
Eclipse出现下面两条报错: The project cannot be built until build path errors are resolved HelloWord Unknown ...
- React Native 开发之 (07) 常用组件-View
掌握了React Native的组件就可以使用IOS的原生组件和API. 一 View组件 就像开发web应用程序中,需要使用很多的HTML标签.例如 div,form.但是在基于DIV+CSS布局的 ...
- mysql数据库添加索引优化查询效率
项目中如果表中的数据过多的话,会影响查询的效率,那么我们需要想办法优化查询,通常添加索引就是我们的选择之一: 1.添加PRIMARY KEY(主键索引) mysql>ALTER TABLE `t ...
- MySQL中的外键是什么、有什么作用
本文参加博文大赛,如果您满意的话麻烦点击这里给我投票原,查看原文点击这里.最近自学数据库MySQL,然后有个疑问,一直不得其解,查询了相关资料,最后还是没有解决. 我的疑问是 "使用外键约束 ...
- docker image重命名
use docker tag command tag Tag an image into a repository
- Java工厂设计模式
程序在接口和子类之间加入一个过渡类,通过此过渡类端取得接口的实例化对象,一般都会称这个过渡端为工厂类 //=============================================== ...
- linux 开机启动过程详解
Linux开机执行内核后会启动init进程,该进程根据runlevel(如x)执行/etc/rcx.d/下的程序,其下的程序是符号链接,真正的程序放在/etc/init.d/下.开机启动的程序(服务等 ...