一、说明

    异步加载就是把消耗程序时间比较大的加载操作放到其他线程中,待加载完毕后通过回调函数的方式通知主线程。
 
addImageAsync函数实现(Cocos2dx 3.3)

Link: http://codepad.org/UuNcXMqq    [ raw code | fork ]  
 
void TextureCache::addImageAsync(const std::string &path, const std::function<void(Texture2D*)>& callback)
{
Texture2D *texture = nullptr; std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path); auto it = _textures.find(fullpath);
if( it != _textures.end() )
texture = it->second; if (texture != nullptr)
{
callback(texture);
return;
} // lazy init
if (_asyncStructQueue == nullptr)
{
_asyncStructQueue = new queue<AsyncStruct*>();
_imageInfoQueue = new deque<ImageInfo*>(); // create a new thread to load images
_loadingThread = new std::thread(&TextureCache::loadImage, this); _needQuit = false;
} if ( == _asyncRefCount)
{
Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(TextureCache::addImageAsyncCallBack), this, , false);
} ++_asyncRefCount; // generate async struct
AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback); // add async struct into queue
_asyncStructQueueMutex.lock();
_asyncStructQueue->push(data);
_asyncStructQueueMutex.unlock(); _sleepCondition.notify_one();
}
异步加载实例:
    ImageAsync.lua

Link: http://codepad.org/ydr3m4bK    [ raw code | fork ]  
--图片异步加载
ImageAsync=class("ImageAsync",function()
return cc.Layer:create()
end) ImageAsync.ctor=function(self)
self.size=cc.Director:getInstance():getWinSize()
self:initTexture()
self:loadingLabel()
self.curIndex= --当前loaded的图片编号 self:registerScriptHandler(function(tag)
if tag=="enter" then
--设置定时器
self:scheduleUpdateWithPriorityLua(function(dt)
self:loadTexture()
end,)
elseif tag=="exit" then
cclog("exit")
self:unscheduleUpdate()
cc.Director:getInstance():getTextureCache():removeAllTextures()
end
end)
end --初始化loadding label
ImageAsync.loadingLabel=function(self)
local label=cc.Label:createWithTTF("Loading...0%", "res/fonts/arial.ttf", )
label:setPosition(self.size.width/,self.size.height/)
self:addChild(label)
self.label=label
end --初始化图片集
ImageAsync.initTexture=function(self)
self.textures={}
for i=, do
for j=, do
local image=string.format("Images/sprites_test/sprite-%d-%d.png",i,j)
table.insert(self.textures,image)
end
end
end --异步加载图片
ImageAsync.loadTexture=function(self)
local function loadedImage(texture)
local sprite=cc.Sprite:createWithTexture(texture)
sprite:setPosition(cc.p(self.size.width/,self.size.height/))
sprite:setScale()
self:addChild(sprite)
self.curIndex=self.curIndex+
self.label:setString(string.format("Loading...%d%%",math.floor(*self.curIndex/#self.textures)))
cclog(string.format("loaded self.textures[%d]:%s",self.curIndex,self.textures[self.curIndex]))
end local textureCache=cc.Director:getInstance():getTextureCache()
for i=,#self.textures do
textureCache:addImageAsync(self.textures[i],loadedImage)
end self:unscheduleUpdate()
end ImageAsync.create=function()
local layer=ImageAsync.new()
return layer
end return ImageAsync
执行效果:
    
 
补充说明:
    Cocos2dx TextureCache会加载图片到内存中,创建Sprite  initWithFile时如果内存中已经有该texture直接使用该texture,这样就达到了减少切换界面时出现的卡顿(直接从内存中取资源,而非IO操作),具体实现如下:
    
 
TextureCache的addImage实现如下:
Texture2D * TextureCache::addImage(const std::string &path)
{
Texture2D * texture = nullptr;
Image* image = nullptr;
// Split up directory and filename
// MUTEX:
// Needed since addImageAsync calls this method from a different thread std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);
if (fullpath.size() == )
{
return nullptr;
}
auto it = _textures.find(fullpath);
if( it != _textures.end() )
texture = it->second; if (! texture)
{
// all images are handled by UIImage except PVR extension that is handled by our own handler
do
{
image = new (std::nothrow) Image();
CC_BREAK_IF(nullptr == image); bool bRet = image->initWithImageFile(fullpath);
CC_BREAK_IF(!bRet); texture = new (std::nothrow) Texture2D(); if( texture && texture->initWithImage(image) )
{
#if CC_ENABLE_CACHE_TEXTURE_DATA
// cache the texture file name
VolatileTextureMgr::addImageTexture(texture, fullpath);
#endif
// texture already retained, no need to re-retain it
_textures.insert( std::make_pair(fullpath, texture) );
}
else
{
CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache", path.c_str());
}
} while ();
} CC_SAFE_RELEASE(image); return texture;
}
 
补充说明:
    异步加载plist和png图片——方法是在异步加载png图片的回调函数中,加载plist文件
    Link: http://codepad.org/BuWR4Hdl    [ raw code | fork ]
 
local BaseLoading=class("BaseLoading",function()
return cc.Layer:create()
end) BaseLoading.init=function(self)
self._size=cc.Director:getInstance():getWinSize()
self._textures={}
self._curIndex= --当前loaded的图片编号 self:initTexture()
self:loadingUI()
end --需要加载的所有资源文件
BaseLoading.initTexture=function(self) end --异步加载图片
BaseLoading.loadTexture=function(self)
local frameCache=cc.SpriteFrameCache:getInstance()
--加载图片
local function loadPng(texture)
self._label:setString(string.format("Loading...%d%%",math.floor(*self._curIndex/#self._textures)))
cclog(string.format("loaded self.textures[%d]:%s",self._curIndex,self._textures[self._curIndex].loc..".png"))
if self._curIndex==#self._textures then
self:finishLoading()
end
self._curIndex=self._curIndex+
end --加载Plist图片
local function loadPlist(texture)
frameCache:addSpriteFrames(self._textures[self._curIndex].loc..".plist")
self._label:setString(string.format("Loading...%d%%",math.floor(*self._curIndex/#self._textures)))
cclog(string.format("loaded self.textures[%d]:%s",self._curIndex,self._textures[self._curIndex].loc..".png"))
if self._curIndex==#self._textures then
self:finishLoading()
end
self._curIndex=self._curIndex+
end local textureCache=cc.Director:getInstance():getTextureCache()
for i=,#self._textures do
local rtype=self._textures[i].rtype
if rtype=="png" then
textureCache:addImageAsync(self._textures[i].loc..".png",loadPng)
elseif rtype=="plist" then
textureCache:addImageAsync(self._textures[i].loc..".png",loadPlist)
end
end
self:unscheduleUpdate()
end --loading UI
BaseLoading.loadingUI=function(self)
local label=cc.Label:createWithTTF("Loading...0%", "res/fonts/Marker Felt.ttf", )
label:setPosition(self._size.width/,self._size.height/)
self:addChild(label)
self._label=label
end BaseLoading.startLoading=function(self)
self:registerScriptHandler(function(tag)
if tag=="enter" then
--设置定时器
self:scheduleUpdateWithPriorityLua(function(dt)
self:loadTexture()
end,)
elseif tag=="exit" then
self:unscheduleUpdate()
end
end)
end --完成异步加载图片回调函数
BaseLoading.finishLoading=function(self) end return BaseLoading
补充说明:
    异步加载plist纹理和png图片
    加载plist时,先加载plist对应的png图片,加载plist对应的png图片之后,在异步回调函数中,将plist载入textureCache中
 
 

【Cocos2dx3.x Lua】图片异步加载的更多相关文章

  1. cocos2dx lua中异步加载网络图片,可用于显示微信头像

    最近在做一个棋牌项目,脚本语言用的lua,登录需要使用微信登录,用户头像用微信账户的头像,微信接口返回的头像是一个url,那么遇到的一个问题就是如何在lua中异步加载这个头像,先在引擎源码里找了下可能 ...

  2. Android-Universal-Image-Loader 图片异步加载类库的使用

    在博客中看到一篇利用组件进行图片异步加载的文章在此作记录 原文:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载并缓存的 ...

  3. Android图片异步加载框架Android-Universal-Image-Loader

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个 ...

  4. Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)

    这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚 ...

  5. Android ListView 图片异步加载和图片内存缓存

    开发Android应用经常需要处理图片的加载问题.因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载.为了增加用户体验,给用 ...

  6. Android 图片异步加载的体会,SoftReference已经不再适用

      在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>>  这样软引用的 ...

  7. 【转】Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)

    Android-Universal-Image-Loader 原文地址:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载 ...

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

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

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

    今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决 ...

随机推荐

  1. mysql数据库中的存储引擎是什么意思呢

    需求描述: 在看mysql的内容,经常提到存储引擎,那么到底什么是存储引擎呢 在这里对于概念进行理解,记录下. 概念解释: 存储引擎(storage engine):存储引擎就是mysql中的一个组件 ...

  2. [extjs] ExtJs4.2 Form 表单提交

    基本代码: <script> Ext.onReady(function(){ Ext.create('Ext.form.Panel', { title: '登录', bodyPadding ...

  3. PHP-001

    ThinkPHP单字母函数(快捷方法)使用总结 http://www.cnblogs.com/caicaizi/p/5173093.html

  4. TCP异常关闭研究分析

    版权声明:本文由谢代斌原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/108 来源:腾云阁 https://www.qclo ...

  5. Java初学者笔记五:泛型处理

    一.泛型类: 泛型是指适用于某一种数据类型而不是一个数据机构中能存不同类型 import java.io.*; import java.nio.file.Files; import java.nio. ...

  6. 【黑金ZYNQ7000系列原创视频教程】07.自定义IP——定制RTC IP实验

    黑金论坛地址: http://www.heijin.org/forum.php?mod=viewthread&tid=36641&extra=page%3D1 爱奇艺地址: http: ...

  7. C#如何判断程序调用的exe已结束

    二个方法:以运行系统记事本为例 方法一:这种方法会阻塞当前进程,直到运行的外部程序退出System.Diagnostics.Process exep = System.Diagnostics.Proc ...

  8. OC开发_Storyboard——AutoLayout

    一.autolayout 自动布局: 1. 设置所有视图框架的三种方法,可以通过代码创建也可以storyboard设置 = 规则 (1 蓝线+约束:(位置) 使用蓝线,根据蓝线拖动控件,只是告诉Xco ...

  9. 模拟退火算法(西安网选赛hdu5017)

    Ellipsoid Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

  10. Linux定时对日志批量打包Shell脚本及定时任务crontab 详细用法

    一.需求背景     因此次项目的生产环境中部署了多套系统,每天会产生大量的日志(数百GB的量),侵占了服务器宝贵的存储资源空间.为了有效缓解服务器存储压力,考虑通过Linux的Shell脚本结合cr ...