• Cocos2d-x3.2 TextureCache类异步载入功能解说


    本文TextureCache类异步载入功能的代码抽出,总共代码就200多行。感兴趣能够看看。

    研究这个主要是由于项目中须要异步插入数据,但之前的方法在Android上总是崩溃所以想到TextureCache有异步载入的功能就将其抽出了。

    原文地址:http://blog.csdn.net/qqmcy/article/details/39890837

    代码下载:http://download.csdn.net/detail/qqmcy/8011589


    首先。创建AsyncTaskTime类,主要模拟一个费时的方法

    AsyncTaskTime.h

    #include "cocos2d.h"
    
    USING_NS_CC;
    
    class AsyncTaskTime
    {
    public:
        
        //模拟一个费时操作
        bool initWithImageFileThreadSafe(const std::string &filename);
        
        
    };
    

    AsyncTaskTime.cpp

    //
    //  AsyncTaskTime.cpp
    //  cpp4
    //
    //  Created by 杜甲 on 10/8/14.
    //
    //
    
    #include "AsyncTaskTime.h"
    
    bool AsyncTaskTime::initWithImageFileThreadSafe(const std::string &filename)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(3000));
        return true;
    }

    创建异步载入功能类

    AsyncTest.h

    //
    //  AsyncTest.h
    //  cpp4
    //
    //  Created by 杜甲 on 10/8/14.
    //
    //
    
    #ifndef __cpp4__AsyncTest__
    #define __cpp4__AsyncTest__
    
    #include "cocos2d.h"
    #include "AsyncTaskTime.h"
    
    using namespace std;
    
    USING_NS_CC;
    class AsyncTest : public Ref
    {
    public:
        CREATE_FUNC(AsyncTest);
        
        virtual bool init();
        
        AsyncTest();
        
        // 异步载入
        void addImageAsync(const string &path , const function<void(AsyncTaskTime *)> &callback);
    private:
        
        void addImageAsyncCallback(float dt);
        //载入数据
        void loadImage();
        
    public:
        struct AsyncStruct
        {
        public:
            AsyncStruct(const string &fn , function<void(AsyncTaskTime *)> f): filename(fn) , callback(f){};
            
            string filename;
            function<void(AsyncTaskTime *)> callback;
        };
        
    protected:
        
        typedef struct
        {
            AsyncStruct *asyncStruct;
            AsyncTaskTime *image;
        }ImageInfo;
        
        
        thread *_loadingThread;
        queue<AsyncStruct *>        *_asyncStructQueue;
        deque<ImageInfo *>          *_ImageInfoQueue;
        
        mutex                       _asyncStructQueueMutex;
        mutex                       _imageInfoMutex;
        
        mutex                       _sleepMutex;
        condition_variable          _sleepCondition;
        
        bool                        _needQuit;
        int                         _asyncRefCount;
        unordered_map<std::string , AsyncTaskTime* > _textures;
        
        
        
        
    };
    
    #endif /* defined(__cpp4__AsyncTest__) */
    

    AsyncTest.cpp

    //
    //  AsyncTest.cpp
    //  cpp4
    //
    //  Created by 杜甲 on 10/8/14.
    //
    //
    
    #include "AsyncTest.h"
    
    AsyncTest::AsyncTest()
    : _loadingThread(nullptr)
    , _asyncStructQueue(nullptr)
    , _ImageInfoQueue(nullptr)
    , _needQuit(false)
    , _asyncRefCount(0)
    {
        
    }
    
    bool AsyncTest::init()
    {
        return true;
    }
    
    void AsyncTest::addImageAsync(const string &path, const function<void (AsyncTaskTime *)> &callback)
    {
        AsyncTaskTime *texture = nullptr;
        
        auto it = _textures.find(path);
        if (it != _textures.end()) {
            texture = it->second;
        }
        
        if (texture != nullptr) {
            callback(texture);
            return;
        }
        
        if (_asyncStructQueue == nullptr) {
            _asyncStructQueue = new queue<AsyncStruct *>();
            _ImageInfoQueue = new deque<ImageInfo *>();
            
            _loadingThread = new thread(&AsyncTest::loadImage , this);
            
            _needQuit = false;
        }
        
        if (0 == _asyncRefCount) {
            Director::getInstance()->getScheduler()->schedule(schedule_selector(AsyncTest::addImageAsyncCallback), this, 0, false);
        }
        
        ++_asyncRefCount;
        
        auto data = new AsyncStruct(path , callback);
        
        _asyncStructQueueMutex.lock();
        _asyncStructQueue->push(data);
        _asyncStructQueueMutex.unlock();
        
        _sleepCondition.notify_one(); //将等待 condition_variable 对象的当中一个线程解除堵塞。

    } void AsyncTest::loadImage() { AsyncStruct *asyncStruct = nullptr; while (true) { queue<AsyncStruct *> *pQueue = _asyncStructQueue; _asyncStructQueueMutex.lock(); if (pQueue->empty()) { } else{ asyncStruct = pQueue->front(); pQueue->pop(); _asyncStructQueueMutex.unlock(); } AsyncTaskTime *image = nullptr; bool generateImage = false; auto it = _textures.find(asyncStruct->filename); if (it == _textures.end()) { _imageInfoMutex.lock(); ImageInfo *imageInfo; size_t pos = 0; size_t infoSize = _ImageInfoQueue->size(); for (; pos < infoSize; pos++) { imageInfo = (*_ImageInfoQueue)[pos]; if (imageInfo->asyncStruct->filename.compare(asyncStruct->filename) == 0) break; } _imageInfoMutex.unlock(); if (infoSize == 0 || pos == infoSize) generateImage = true; } if (generateImage) { const string &filename = asyncStruct->filename; image = new AsyncTaskTime(); if (image && !image->initWithImageFileThreadSafe(filename)) { continue; } } auto imageInfo = new ImageInfo(); imageInfo->asyncStruct = asyncStruct; imageInfo->image = image; _imageInfoMutex.lock(); _ImageInfoQueue->push_back(imageInfo); _imageInfoMutex.unlock(); } if (_asyncStructQueue != nullptr) { delete _asyncStructQueue; _asyncStructQueue = nullptr; delete _ImageInfoQueue; _ImageInfoQueue = nullptr; } } void AsyncTest::addImageAsyncCallback(float dt) { deque<ImageInfo *> *imagesQueue = _ImageInfoQueue; _imageInfoMutex.lock(); if (imagesQueue->empty()) { _imageInfoMutex.unlock(); } else{ auto imageInfo = imagesQueue->front(); imagesQueue->pop_front(); _imageInfoMutex.unlock(); auto asyncStruct = imageInfo->asyncStruct; auto image = imageInfo->image; if (asyncStruct->callback) { asyncStruct->callback(image); } --_asyncRefCount; if (0 == _asyncRefCount) { Director::getInstance()->getScheduler()->unschedule(schedule_selector(AsyncTest::addImageAsyncCallback), this); } } }



    调用:

    HelloWorldScene.h  

    #ifndef __HELLOWORLD_SCENE_H__
    #define __HELLOWORLD_SCENE_H__
    
    #include "cocos2d.h"
    #include "AsyncTest.h"
    USING_NS_CC;
    
    
    class HelloWorld : public cocos2d::Layer
    {
    public:
        // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
        
        HelloWorld();
        
        virtual bool init();  
    
        // there's no 'id' in cpp, so we recommend returning the class instance pointer
        static cocos2d::Scene* scene();
        
       
        
        // implement the "static node()" method manually
        CREATE_FUNC(HelloWorld);
        
        
    private:
        Size winSize;
        //这里加入一个回调方法
        void loadCallback1(AsyncTaskTime *time);
        
    };
    
    #endif // __HELLOWORLD_SCENE_H__
    

    HelloWorldScene.cpp

    // on "init" you need to initialize your instance
    bool HelloWorld::init()
    {
        //////////////////////////////
        // 1. super init first
        if ( !Layer::init() )
        {
            return false;
        }
        
        auto as = AsyncTest::create();
        as->retain();
        as->addImageAsync("test", CC_CALLBACK_1(HelloWorld::loadCallback1, this));
        
        
        
           
        return true;
    }
    
    void HelloWorld::loadCallback1(AsyncTaskTime *time)
    {
        
        log("载入完毕");
        
    }


    控制台:

    cocos2d: 载入完毕


    这样我们就将TextureCache中

     virtual void addImageAsync(conststd::string &filepath, const std::function<void(Texture2D*)>& callback);

    这个异步载入数据的功能实现了。















  • 相关阅读:
    ios 重构笔记
    ios uiwindow笔记
    ios静态库笔记
    ios app提交之前需要哪几个证书
    int、long、long long取值范围
    字节概述
    序列化概述
    LeetCode 最大连续子数列值
    198. LeetCode 打家劫舍
    git自定义关键字
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/5073877.html
Copyright © 2020-2023  润新知