zoukankan      html  css  js  c++  java
  • 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 : 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.
    问题到此结束了吗?我也以为结束了,然后又发现新问题。
    一旦我给场景过渡加上效果,以上方法就不灵验了,释放失败。

    1
    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 执行后过一段时间,
    再调用释放资源的方法,这样就可以确保资源被释放。

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




    5.
    以上方法的确是可以将资源释放掉,但是不是我们所要的”最佳时机”呢?
    仔细观察,B场景的init是在A场景的释放之前的,也就是说,在B场景诞生,A场景彻底释放
    的短时间内,会存在A,B场景的所有资源共存的现在。这个时候内存达到巅峰。如果A场景
    跟B场景的资源所占内存都非常大的时候,或许会造成崩溃。
    那么我们应该如何解决?

    目前我的解决方法就是在场景过渡的时候增加一个过渡场景,也就是Loading场景,Loading场景
    本身所需的资源并不多,在A场景资源释放完毕后,再开启B场景的资源加载。

  • 相关阅读:
    CF1117G Recursive Queries
    P6604 [HNOI2016]序列 加强版
    高级图论
    P7708「Wdsr-2.7」八云蓝自动机 Ⅰ
    ISIJ2020 游记
    计算几何笔记 (模板)
    AC自动机学习笔记
    KMP学习笔记
    treap学习笔记
    HolyK学长的杂题选讲
  • 原文地址:https://www.cnblogs.com/jeason1997/p/4813613.html
Copyright © 2011-2022 走看看