如果没有预先加载图片,则可以通过addImageAsync()函数实现异步加载,该函数通过创建一个加载线程来加载图片,并且在主线程中通过调用回调函数来读取该图片资源纹理。其主要过程如下:

1.创建线程,用于后台加载图片

2.将对于需要加载的图片放入图片资源队列中

3.callback函数设定,用于将加载完成的图片转为纹理,等待使用其调用是由CCTimer::update调用的。

4.addImageAsyncCallBack函数在处理完纹理转换,还会调用addImageAsync传入的SEL_CallFuncO selector,实现用户加载图片纹理之后的具体处理。

 
void addImageAsync(const char *path, CCObject *target, SEL_CallFuncO selector);
函数实现过程如下:
void CCTextureCache::addImageAsync(const char *path, CCObject *target, SEL_CallFuncO selector)
{
    CCAssert(path != NULL, “TextureCache: fileimage MUST not be NULL”);
 
    CCTexture2D *texture = NULL;
 
    // optimization
 
    std::string pathKey = path;
 
    pathKey = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(pathKey.c_str());
    texture = (CCTexture2D*)m_pTextures->objectForKey(pathKey.c_str());
 
    std::string fullpath = pathKey;
    if (texture != NULL)
    {
        if (target && selector)
        {
            (target->*selector)(texture);
        }
 
        return;
    }
 
    // lazy init
    if (s_pSem == NULL)
    {
#if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE
        s_pSem = sem_open(CC_ASYNC_TEXTURE_CACHE_SEMAPHORE, O_CREAT, 0644, 0);
        if( s_pSem == SEM_FAILED )
        {
            CCLOG( “CCTextureCache async thread semaphore init error: %s\n”, strerror( errno ) );
            s_pSem = NULL;
            return;
        }
#else
        int semInitRet = sem_init(&s_sem, 0, 0);
        if( semInitRet < 0 )
        {
            CCLOG( “CCTextureCache async thread semaphore init error: %s\n”, strerror( errno ) );
            return;
        }
        s_pSem = &s_sem;
#endif
          //创建一个异步信息队列
        s_pAsyncStructQueue = new queue<AsyncStruct*>();
          //创建一个图片资源队列
         s_pImageQueue = new queue<ImageInfo*>();      
 
        pthread_mutex_init(&s_asyncStructQueueMutex, NULL);
        pthread_mutex_init(&s_ImageInfoMutex, NULL);
 
        //创建加载图片资源线程,用于加载图片
        pthread_create(&s_loadingThread, NULL, loadImage, NULL);
 
        need_quit = false;
    }
 
    if (0 == s_nAsyncRefCount)
    {
        //创建调度队列,用来根据已加载图片来进行纹理转换
        CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack), this, 0, false);
    }
 
    ++s_nAsyncRefCount;
 
    if (target)
    {
        target->retain();
    }
 
    // generate async struct
    AsyncStruct *data = new AsyncStruct();
    data->filename = fullpath.c_str();
    data->target = target;
    data->selector = selector;
 
    // add async struct into queue
    pthread_mutex_lock(&s_asyncStructQueueMutex);
    //将需要加载的图片放入异步信息队列
    s_pAsyncStructQueue->push(data);
    pthread_mutex_unlock(&s_asyncStructQueueMutex);
 
    sem_post(s_pSem);
}
 
创建图片资源
static void* loadImage(void* data)
{
    // create autorelease pool for iOS
    CCThread thread;
    thread.createAutoreleasePool();
 
    AsyncStruct *pAsyncStruct = NULL;
 
    while (true)
    {
        // wait for rendering thread to ask for loading if s_pAsyncStructQueue is empty
        int semWaitRet = sem_wait(s_pSem);
        if( semWaitRet < 0 )
        {
            CCLOG( “CCTextureCache async thread semaphore error: %s\n”, strerror( errno ) );
            break;
        }
 
        //从异步信息队列中取出
        std::queue<AsyncStruct*> *pQueue = s_pAsyncStructQueue;
 
        pthread_mutex_lock(&s_asyncStructQueueMutex);// get async struct from queue
        if (pQueue->empty())
        {
            pthread_mutex_unlock(&s_asyncStructQueueMutex);
            if (need_quit)
                break;
            else
                continue;
        }
        else
        {
            pAsyncStruct = pQueue->front();
            pQueue->pop();
            pthread_mutex_unlock(&s_asyncStructQueueMutex);
        }
 
        const char *filename = pAsyncStruct->filename.c_str();
 
        // compute image type
        CCImage::EImageFormat imageType = computeImageFormatType(pAsyncStruct->filename);
        if (imageType == CCImage::kFmtUnKnown)
        {
            CCLOG(“unsupported format %s”,filename);
            delete pAsyncStruct;
 
            continue;
        }
 
        //创建图片资源 
        CCImage *pImage = new CCImage();
        if (! pImage->initWithImageFileThreadSafe(filename, imageType))
        {
            delete pImage;
            CCLOG(“can not load %s”, filename);
            continue;
        }
 
        // 创建图片资源信息
        ImageInfo *pImageInfo = new ImageInfo();
        pImageInfo->asyncStruct = pAsyncStruct;
        pImageInfo->image = pImage;
        pImageInfo->imageType = imageType;
 
        // 把图片资源加入图片资源队列
        pthread_mutex_lock(&s_ImageInfoMutex);
        s_pImageQueue->push(pImageInfo);
        pthread_mutex_unlock(&s_ImageInfoMutex);
    }
 
    if( s_pSem != NULL )
    {
    #if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE
        sem_unlink(CC_ASYNC_TEXTURE_CACHE_SEMAPHORE);
        sem_close(s_pSem);
    #else
        sem_destroy(s_pSem);
    #endif
        s_pSem = NULL;
        delete s_pAsyncStructQueue;
        delete s_pImageQueue;
    }
 
    return 0;
}
 
创建图片纹理
void CCTextureCache::addImageAsyncCallBack(float dt)
{
    // 从图片资源队列中取出
    std::queue<ImageInfo*> *imagesQueue = s_pImageQueue;
 
    pthread_mutex_lock(&s_ImageInfoMutex);
    if (imagesQueue->empty())
    {
        pthread_mutex_unlock(&s_ImageInfoMutex);
    }
    else
    {
        ImageInfo *pImageInfo = imagesQueue->front();
        imagesQueue->pop();
        pthread_mutex_unlock(&s_ImageInfoMutex);
 
        AsyncStruct *pAsyncStruct = pImageInfo->asyncStruct;
        CCImage *pImage = pImageInfo->image;
 
        CCObject *target = pAsyncStruct->target;
        SEL_CallFuncO selector = pAsyncStruct->selector;
        const char* filename = pAsyncStruct->filename.c_str();
 
        // 创建2D纹理
        CCTexture2D *texture = new CCTexture2D();
#if 0 //TODO: (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
        texture->initWithImage(pImage, kCCResolutioniPhone);
#else
        texture->initWithImage(pImage);
#endif
 
#if CC_ENABLE_CACHE_TEXTURE_DATA
       // cache the texture file name
       VolatileTexture::addImageTexture(texture, filename, pImageInfo->imageType);
#endif
 
        // 加入缓存
        m_pTextures->setObject(texture, filename);
        texture->autorelease();
 
        if (target && selector)
        {
            (target->*selector)(texture);
            target->release();
        }
 
        pImage->release();
        delete pAsyncStruct;
        delete pImageInfo;
 
        –s_nAsyncRefCount;
        if (0 == s_nAsyncRefCount)
        {
            CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack), this);
        }
    }
}

cocos2d-x中CCTextureCache图片资源的异步加载的更多相关文章

  1. cocos2d-x中CCTextureCache图片资源的异步加载<转>

    如果没有预先加载图片,则可以通过addImageAsync()函数实现异步加载,该函数通过创建一个加载线程来加载图片,并且在主线程中通过调用回调函数来读取该图片资源纹理.其主要过程如下: 1.创建线程 ...

  2. MVC中实现部分内容异步加载

    MVC中实现部分内容异步加载 action中定义一个得到结果集的方法 public ActionResult GetItemTree(string title, int itemid, int? pa ...

  3. vue-awesome-swiper中的数据异步加载

    <template> <div> //第一个轮播 加了v-if 判断,可以实现 loop 轮循 <swiper v-if="gglist.length>1 ...

  4. 【Cocos2d-Js基础教学(5)资源打包工具的使用及资源的异步加载处理】

    TexturePacker是纹理资源打包工具,支持Cocos2dx的游戏资源打包. 如果用过的同学可以直接看下面的资源的异步加载处理 首先为什么用TexturePacker? 1,节省图片资源实际大小 ...

  5. Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...

  6. [置顶] 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

    转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<Strin ...

  7. 使用 jsPlumb 绘制拓扑图 —— 异步加载与绘制的实现

    本文实现的方法可以边异步加载数据边绘制拓扑图. 有若干点需要说明一下: 1.  一次性获取所有数据并绘制拓扑图, 请参见文章: <使用 JsPlumb 绘制拓扑图的通用方法> ; 本文实现 ...

  8. Listview 异步加载图片之优化篇(有图有码有解释)

    在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...

  9. Android图片异步加载之Android-Universal-Image-Loader

    将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...

随机推荐

  1. 配置spring管理的bean的作用域

    .singleton 在每一个spring Ioc容器中一个bean定义只有一个对象实例.默认情况下会在容器启动时初始化bean,但我们可以指定bean节点的lazy-init = "tru ...

  2. HTML5新增属性

    [sourcecode language="plain"] <!DOCTYPE html> <html manifest="cache.manifest ...

  3. 【Siverlight - 扩展篇】Silverlight在OOB模式下实现默认打开最大化

      在App.xaml.cs中输入以下代码:在OOB客户端打开,可以实现窗口默认最大化: private void Application_Startup(object sender, Startup ...

  4. 2款好用的Web在线编辑器

    1.CKEditor FCKEditor 现在已经重新开发,并改名为 CKEditor. CKeditor是一个专门使用在网页上,开放源代码,高度可定制,跨平台的所见即所得文字编辑器,兼容于绝大部分的 ...

  5. HDU 1002 分类: ACM 2015-06-18 23:03 9人阅读 评论(0) 收藏

    昨天做的那题其实和大整数相加类似.记得当初我大一寒假就卡在这1002题上,结果之后就再也没写题... 到今天终于把大整数相加写了一遍. 不过写的很繁琐,抽时间改进一下写简洁一点. #include&l ...

  6. socket对于大数据的发送和接收

    大数据是指大于32K或者64K的数据. 大数据的发送和接收通过TSTREAM对象来进行是非常方便的. 我们把大数据分割成一个个4K大小的小包,然后再依次传输. 一.大数据的发送的类语言描述: 1)创建 ...

  7. Arduino 模拟信号的读入并转化为0-5V电压

    int ledIn = A0; void setup(){ Serial.begin(9600); } void loop(){ int sensorValue = analogRead(ledIn) ...

  8. POJ2947Widget Factory(高斯消元解同模方程)

    http://poj.org/problem?id=2947 题目大意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下:p start enda1,a2......ap (1<=ai&l ...

  9. CodeForces 702B Powers of Two (暴力,优化)

    题意:给定 n 个数,问你从有多少下标 i < j,并且 ai + aj 是2的倍数. 析:方法一: 从输入开始暴力,因为 i < j 和 i > j 是一样,所以可以从前面就开始查 ...

  10. 手把手教你玩转SOCKET模型之重叠I/O篇(下)

    四.     实现重叠模型的步骤 作 了这么多的准备工作,费了这么多的笔墨,我们终于可以开始着手编码了.其实慢慢的你就会明白,要想透析重叠结构的内部原理也许是要费点功夫,但是只是学会 如何来使用它,却 ...