本文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);

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



Cocos2d-x3.2 TextureCache类异步载入功能解说的更多相关文章

  1. cocos2dx3.2 异步载入和动态载入

    半个月没有更新博客,从这个项目開始学习了非常多细节的东西,都不太成系统.可是却是开发上线中必须经历的东西.比方超级玛丽系列(一)中的正确的异步载入,正确的分层.正确的合成和载入plist.及时的移除未 ...

  2. Mvc音乐商店demo的ajax异步删除功能总结

    刚刚从学校出来参加工作,没啥工作经验,所以各位大神们不要嘲笑哈! 来公司后要进行培训,给我们的作业中有一个使用 dapper+mvc+ajax+SQL Server 2008,来实现一个音乐商店的de ...

  3. Android异步载入全解析之使用多线程

    异步载入之使用多线程 初次尝试 异步.异步,事实上说白了就是多任务处理.也就是多线程执行.多线程那就会有各种问题,我们一步步来看.首先.我们创建一个class--ImageLoaderWithoutC ...

  4. structs2注解+jsp+ajax实现post异步载入select

    流程: 1.点击载入btn发起异步请求post 2.后台处理请求返回数据 3.前端获取数据成功,对数据进行处理 前端: html:首先要导入jq包,不然怎么用ajax呢. <script typ ...

  5. Android异步载入全解析之IntentService

    Android异步载入全解析之IntentService 搞什么IntentService 前面我们说了那么多,异步处理都使用钦定的AsyncTask.再不济也使用的Thread,那么这个Intent ...

  6. PHP设计模式:类自动载入、PSR-0规范、链式操作、11种面向对象设计模式实现和使用、OOP的基本原则和自动加载配置

    一.类自动载入 SPL函数 (standard php librarys) 类自动载入,尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_registe ...

  7. UE4异步载入资源

    转自:http://blog.ch-wind.com/ue4%E5%BC%82%E6%AD%A5%E8%BD%BD%E5%85%A5%E8%B5%84%E6%BA%90/ 所有的“硬”指针指向的资源都 ...

  8. Android异步载入全解析之使用AsyncTask

    Android异步载入全解析之使用AsyncTask 概述 既然前面提到了多线程,就不得不提到线程池,通过线程池,不仅能够对并发线程进行管理.更能够提高他们运行的效率.优化整个App.当然我们能够自己 ...

  9. ListView的异步载入(笔记,多线程和AsyncTask)

    异步载入最经常使用的两种方式: 多线程,线程池     AsyncTask 实例操作: 从一个站点上获取Json数据.然后将数据在ListView上显示. 1.创建item_layout布局 , 改动 ...

随机推荐

  1. golang基础之一

    一.第一个go程序 package main import ( "fmt" ) func main(){ fmt.Println("hello world") ...

  2. python基础(11)--面向对象

    1.概述 面向过程:根据业务的逻辑从上到下写代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发更快更好更强 面向过程编程最易被初学者接受 ...

  3. Jenkins+Ant+SVN+Jmeter实现持续集成

     一.什么是持续集成? 待补充 二.说明: 本次框架介绍中不涉及到介绍框架的构建过程,介绍如何构建环境详细的构建见前篇文章: jmeter+Jenkins持续集成(邮件通知) Jmeter+Jenki ...

  4. Fresco 获得Bitmap

    ImageRequest imageRequest = ImageRequestBuilder .newBuilderWithSource( Uri.parse(getFeedItem(positio ...

  5. 二叉排序树实现(C++封装)

    设计思路 设计一个类,根结点只可读取,具备构造二叉树.插入结点.删除结点.查找. 查找最大值.查找最小值.查找指定结点的前驱和后继等功能接口. 二叉排序树概念 它或者是一棵空树:或者是具有下列性质的二 ...

  6. 二十二 使用__slots__

    正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: class Student(object): pa ...

  7. HTML 如何显示英文单、双引号

    // 过滤英文引号替换成中文引号 function pregstring($str){ return preg_replace('/"([^"]*)/','&quot${1 ...

  8. git使用注意点

    1. 如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字$ git clone git://github.com/schacon/grit.git mygrit 2. ...

  9. Java常用工具类之Excel导出

    package com.wazn.learn.util; import java.util.List; import java.util.Map; import org.apache.poi.hssf ...

  10. /etc/default/useradd配置文件详解

    /etc/default/useradd文件内容如下: [xf@xuexi ~]$ cat /etc/default/useradd # useradd defaults file GROUP=100 ...