如果没有预先加载图片,则可以通过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, , );
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, , );
if( semInitRet < )
{
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 ( == s_nAsyncRefCount)
{
//创建调度队列,用来根据已加载图片来进行纹理转换
CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack), this, , 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 < )
{
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 ;
}
创建图片纹理
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 ( == 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. 1414. Astronomical Database(STL)

    1414 破题 又逼着用stl 卡内存 trie树太耗了 水不过去 用set存字符串 set可以自己按一定顺序存 且没有重复的 再用lower_bound二分查找字符串的第一次出现 接着往后找就行了 ...

  2. bzoj1056: [HAOI2008]排名系统 && 1862: [Zjoi2006]GameZ游戏排名系统

    hash 加上 平衡树(名次树). 这道题麻烦的地方就在于输入的是一个名字,所以需要hash. 这个hash用的是向后探查避免冲突,如果用类似前向星的方式避免冲突,比较难写,容易挂掉,但也速度快些. ...

  3. bzoj1821: [JSOI2010]Group 部落划分 Group

    kruskal算法. #include<cstdio> #include<algorithm> #include<cstring> #include<cmat ...

  4. BZOJ3509: [CodeChef] COUNTARI

    3509: [CodeChef] COUNTARI Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 85[Submit][St ...

  5. poj2406 周期

    脑残wa了一次 var s:ansistring; ans,i,k,m:longint; pre:..] of longint; function max(x,y:longint):longint; ...

  6. 判断String为空

    1.  et_string.equals("")|| et_string==null 2.  ""用equal.null用== TextUtils.isEmpt ...

  7. Java [Leetcode 104]Maximum Depth of Binary Tree

    题目描述: Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along th ...

  8. Spring AOP--基于XML文件的配置

    Spring AOP的配置可以基于注解,也可以基于XML文件.前面几篇都是使用注解的方式.下面介绍下使用XML文件如何配置 使用的测试类和切面类都类似.只需要属于AOP的注解去掉即可.下面是AOP的X ...

  9. ArcScene三维制作

    转自:http://www.360doc.com/content/11/0818/10/7534722_141363009.shtml 1.0 添加地图数据 数据显示效果: 1.1 设置图层的显示顺序 ...

  10. MFC 状态栏相关使用(CStatusBar & CStatusBarCtrl)

    原文:MFC 状态栏相关使用(CStatusBar & CStatusBarCtrl),沙漠紫风铃 本文介绍了MFC中和状态栏相关的用法: 在MFC的的单文档应用中,在建好应用程序之后,CMa ...