如果没有预先加载图片,则可以通过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图片资源的异步加载<转>
如果没有预先加载图片,则可以通过addImageAsync()函数实现异步加载,该函数通过创建一个加载线程来加载图片,并且在主线程中通过调用回调函数来读取该图片资源纹理.其主要过程如下: 1.创建线程 ...
- MVC中实现部分内容异步加载
MVC中实现部分内容异步加载 action中定义一个得到结果集的方法 public ActionResult GetItemTree(string title, int itemid, int? pa ...
- vue-awesome-swiper中的数据异步加载
<template> <div> //第一个轮播 加了v-if 判断,可以实现 loop 轮循 <swiper v-if="gglist.length>1 ...
- 【Cocos2d-Js基础教学(5)资源打包工具的使用及资源的异步加载处理】
TexturePacker是纹理资源打包工具,支持Cocos2dx的游戏资源打包. 如果用过的同学可以直接看下面的资源的异步加载处理 首先为什么用TexturePacker? 1,节省图片资源实际大小 ...
- Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
Android 高手进阶(21) 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...
- [置顶] 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<Strin ...
- 使用 jsPlumb 绘制拓扑图 —— 异步加载与绘制的实现
本文实现的方法可以边异步加载数据边绘制拓扑图. 有若干点需要说明一下: 1. 一次性获取所有数据并绘制拓扑图, 请参见文章: <使用 JsPlumb 绘制拓扑图的通用方法> ; 本文实现 ...
- Listview 异步加载图片之优化篇(有图有码有解释)
在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...
- Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
随机推荐
- 标准IO
标准IO由ISO C 标准的IO库,它处理了很多底层细节,比如合适的缓冲大小等等,因此更易于使用,但是也引入了一些其他问题. 流向 标准IO使用FILE对象关联流,流可以是面向宽字节的也可以是面向单字 ...
- Educational Codeforces Round 5 A. Comparing Two Long Integers
A. Comparing Two Long Integers time limit per test 2 seconds memory limit per test 256 megabytes inp ...
- Node-APN 开源推送服务
Node-APN是一个开放的结合了苹果推送通知的Node.js模块,该源码模块使用简单,反馈服务支持.错误处理,在发送出错时自动重发.遵从苹果的最佳实践. Node-APN(github)
- mediawiki 的使用 2
要想外部电脑能访问你的网站,网站部署好后,在LocalSettings.php 里将这句 $wgServer = "http://localhost"; 改成 $wgServer ...
- MYSQL数据库重点:事务与锁机制
一.事务 一组连续的数据库操作,每一次操作都成功,整个事务就成功,只要有一步出错,整个事务就失败: MySQL事务与存储引擎相关 1.MyISAM:不支持事务,用于只读程序提高性能 2.InnoDB: ...
- JavaScript面向对象简介
JavaScript面向对象简介 @(编程) [TOC] 1. 命名空间 命名空间是一个容器,它允许开发人员在一个独特的,特定于应用程序的名称下捆绑所有的功能. 在JavaScript中,命名空间只是 ...
- 将表A的数据复制到表B,以及关于主表和子表的删除办法
如果表A的数据结构和表B的数据结构是一样的,字段名字可以不用相同,但是对应的数据类型是一样的 这样的情况下可以用如下的方式实现将表A的数据复制到表B INSERT INTO #TEMP2 SELECT ...
- Codeforces Round #313 (Div. 2) E. Gerald and Giant Chess (Lucas + dp)
题目链接:http://codeforces.com/contest/560/problem/E 给你一个n*m的网格,有k个坏点,问你从(1,1)到(n,m)不经过坏点有多少条路径. 先把这些坏点排 ...
- Tomcat 系统架构与设计模式,第 1 部分: 工作原理(转载)
简介: 这个分为两个部分的系列文章将研究 Apache Tomcat 的系统架构以及其运用的很多经典设计模式.本文是第 1 部分,将主要从 Tomcat 如何分发请求.如何处理多用户同时请求,还有它的 ...
- A Dream
A Dream 2013年10月20日,成都,天气阴,铜牌16.离2012年10月14日长春现场赛刚好隔了一年,刚看了下去年写的总结http://blog.csdn.net/cc_again/arti ...