cocos2.x退出及内存释放终极解决方案

相信很多朋友都有这样的需求,在一个现有的iOS app里嵌入cocos,cocos要能完全释放,重启。
以下是我研究源码后,实现的方案。已经上线验证使用
版本:Cocos Creator 2.4.2
其它版本大同小异,各位看官相应三步走就行
1.停止渲染
在退出viewcontroller之前,一定要保证把cocos runloop先停掉

// stop runloop
cocos2d::Application::getInstance()->onPause();
cocos2d::Application::getInstance()->stop();

2.释放cocos

- (void)cleanup {
    // audio
    cocos2d::AudioEngine::end();
    // network
    cocos2d::network::HttpClient::destroyInstance();
    // application
    if (s_sharedApplication != nullptr) {
        delete s_sharedApplication;
        s_sharedApplication = nullptr;
    }
}

3.修改Application析构
CCApplication-ios.mm

Application::~Application()
{
    _scheduler->removeAllFunctionsToBePerformedInCocosThread();
    _scheduler->unscheduleAll();
 #if USE_AUDIO
    AudioEngine::end();
 #endif
    
    // spine
  #if USE_SPINE
    spine::SkeletonDataMgr::destroyInstance();
  #endif
    // dragonbones
 #if USE_DRAGONBONES
    dragonBones::ArmatureCacheMgr::destroyInstance();
 #endif
    // middleware
 #if USE_MIDDLEWARE
    middleware::MiddlewareManager::destroyInstance();
 #endif
        
    // font
    TTFLabelAtlasCache::destroyInstance();
        
    // stencil
    renderer::StencilManager::destoryInstance();

    EventDispatcher::destroy();
    se::ScriptEngine::destroyInstance();
    
    // stop main loop
    [(MainLoop*)_delegate stopMainLoop];
    [(MainLoop*)_delegate release];
    _delegate = nullptr;
    
    [(CCEAGLView*)_view release];
    _view = nullptr;

    delete _renderTexture;
    _renderTexture = nullptr;
    
    // director
    renderer::DeviceGraphics::destoryInstance();
    
    Configuration::destroyInstance();
    
    FileUtils::destroyInstance();
    
    // clean auto release pool
    PoolManager::destroyInstance();
    
    Application::_scheduler = nullptr;
    Application::_instance = nullptr;
}
5赞

可以考虑出个demo?这种完整方案应该还是有人有需求的 :grin:

我在2.4.3下只要
se::ScriptEngine::destroyInstance();
就崩了,请问你有这种情况么

3.0 请问楼主有研究吗?

必须先分别停掉js和原生端的runloop,再销毁engine,仔细看我的实现流程。否则有个循环还在跑,强行结束,必然崩

好像没有找到cocos2d::Application::getInstance()->stop();
可以给个demo吗?

补充stop方法

void Application::stop()
{
    if (_delegate) {
        [(MainLoop*)_delegate stopMainLoop];
    }
}

会不会产生新的崩溃?

有测试过内存是否会完全释放掉?包括cocos加载进来的图片和其他资源

老铁 2.4.3能用这个方案跑起来么

2.4.3的引擎应该也可以用这套方案吧?

用过,内存会一直暴涨 来回几次就崩了

其实 delete Application的实例应该就可以了 , 大部分的释放操作析构中会处理 ,补充一些没有释放的单例,调用js也释放下。

在2.4.3版本上使用时发现:上面这行代码如果调用了,v8引擎再次进入会crash。
如果注释掉这行代码,crash没有了,但会黑屏。

1赞

感觉se::ScriptEngine里面的cleanup还是要保留,其他的可以删掉。黑屏看看:renderer::DeviceGraphics::destoryInstance();或者renderer::DeviceGraphics::getInstance()->destroy();有没有调用。

也是在探索中。目前的话在解决,重开十多次崩溃的问题。版本是2.4.6

2.4.3版本里的DeviceGraphics没有destroy的方法,是不是要升级到2.4.6?

好像是,我也升级了,既然改就改最新版本的吧,哎,我现在还是有问题,重启个十来次依然会崩溃

@517492609 @a845326948 大佬们,重启多次后会崩的问题解决了吗?

我用这种方式每次退出再重启会增加30M左右的内存。感觉还不如不释放,然后加载一个空页面