zoukankan      html  css  js  c++  java
  • 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);
  • 相关阅读:
    pdf.js使用
    当前时间距离下一个分钟值以0或者5结尾的时间点(单位:毫秒)小于1分钟时,返回下下个以0或5结尾的时间点
    1
    Could not get JDBC Connection; nested exception is java.sql.SQLException: Cannot get a connection, pool error Pool exhausted 异常原因排查
    gcp导出mysql慢日志写入数据库分析
    redis慢日志结构化
    谷歌云监控告警
    google-cloud的sql-rds导出my.cnf
    慢sql 实时钉钉告警
    docker跨网段搭建gp测试环境
  • 原文地址:https://www.cnblogs.com/deepcho/p/cocos2dx-memory-sprite-spriteframe-texture2d.html
Copyright © 2011-2022 走看看