真不好意思,原本星期一要发的网络管理器,由于昨天工作较忙,挪到今天来发了,万分抱歉。
上一节,我们了解UI管理器的详细用法,及一些基础的游戏框架搭建,那么我们基本业务类都已经有了,下面我们就开始添加网络管理,让我们的有游戏能联网,并封装管理器,以便使用。
本篇所用的Cocos2d-x版本为:
Cocos2d-x 3.2
编译器版本
VS2013
CocosStudio 1.5
本篇服务器以PHP为例
Cocos2d-x3.2教程——【我所认识的Cocos2d-x】
六、Cocos2d-x项目—网络管理器篇 具体的NetWork库,我希望大家能够自己详细的去了解其运作,讲的再细,说的再好,不如自己动手去了解其运作道理,这会使你的编程思维更具有开拓性。首先我们的项目已经添加了Network库了,那么下面在我们还需要添加对libcurl_imp.lib的支持,不然项目编译会
报错的。
右键项目,属性——配置属性——链接器——输入——附加依赖项中添加
libcurl_imp.lib
创建一个类,作为我们的网络管理器 类名就叫NetworkManager
然后引用头文件 添加命名空间 及常用函数
NetworkManager.h
//////////////////////////////////////////////////////////////////////////
#ifndef _NET_WORK_MANAGER_H_
#define _NET_WORK_MANAGER_H_
#include "cocos2d.h"
#include "extensions/cocos-ext.h"
#include "network/HttpClient.h"
#include "uimanager/UIManager.h"
//////////////////////////////////////////////////////////////////////////
USING_NS_CC;
USING_NS_CC_EXT;
using namespace std;
using namespace network;
#define GET_G_NET() (NetworkManager::getNewworkManager())
#define GET_G_NET_LOGIC(x,y) (NetworkManager::getNewworkManager()->LoadUILogic(x,y))
#define GET_G_NET_LISTENER(x,y) (NetworkManager::getNewworkManager()->setListenerAndCallfunND(x,y))
#define GET_G_NET_SERVERADD(x) (NetworkManager::getNewworkManager()->setServerAddress(x))
#define GET_G_NET_REQUEST(x) (NetworkManager::getNewworkManager()->RequestUrlAddress(x))
#define GET_G_NET_RR() (NetworkManager::getNewworkManager()->httpRequestBusiness())
struct HttpState
{
bool m_bSucceed; //是否成功;
bool m_bResolve; //是否解析成功;
string m_vResData; //返回数据;
};
enum MyChannel
{
MC_0 = 0, //默认渠道;
MC_T, //测试渠道;
MC_G, //正式渠道;
};
classNetworkManager :public BaseLayer
{
public:
//构造函数;
NetworkManager();
//析构函数;
~NetworkManager();
//静态创建网络管理器;
static NetworkManager*getNewworkManager();
//初始化数据;
bool initNetworkData();
//设置网址首地址;
void setUrlFirst();
//设置服务端地址;
void setServerAddress(string addressStr);
//设置回调类,及回调函数;
void setListenerAndCallfunND(Ref*Listener, SEL_CallFuncND CallFuns);
//请求业务;
void httpRequestBusiness();
//请求地址;
void RequestUrlAddress(stringaddressStr);
//支线程处理网络;
static void threadingSupportNetwork(void*data);
//网络回调;
void onHttpRequestCompleted(HttpClient*sender, HttpResponse *response);
//效验数据;
void efficacyData(string sdata);
//支线程结果监听;
void threadOver(float dt);
protected:
//渠道区分;
int __m_iChannel;
//网址首连接;
string __m_sUrlFirst;
//存储网址;
string __m_sStorageUrl;
//监听者;
Ref* __m_pListener;
//回调地址;
SEL_CallFuncND __m_cCallfuncND;
//支线程结束;
bool __m_bThread;
//网络状态;
HttpState __m_tHttpState;
};
```
NetworkManager.cpp
//////////////////////////////////////////////////////////////////////////
#include"NetworkManager.h"
static NetworkManager* myNewwork;
//测试地址;
#defineLOCATION_TEST "http://www.baidu.com"
//构造函数;
NetworkManager::NetworkManager()
{
//设置超时;
HttpClient::getInstance()->setTimeoutForRead(20);
}
//析构函数;
NetworkManager::~NetworkManager()
{
//退出时必须调用destroyInstance,否则程序崩溃;
HttpClient::getInstance()->destroyInstance();
}
//静态创建网络管理器;
NetworkManager* NetworkManager::getNewworkManager()
{
if (myNewwork == nullptr)
{
myNewwork = new NetworkManager();
//初始化数据;
myNewwork->initNetworkData();
}
return myNewwork;
}
//初始化数据;
bool NetworkManager::initNetworkData()
{
__m_sUrlFirst = "";
__m_iChannel = MC_T;
__m_bThread = false;
__m_tHttpState.m_bSucceed = false;
__m_tHttpState.m_bResolve = false;
__m_tHttpState.m_vResData = "";
setUrlFirst();
return true;
}
//设置网址首地址;
void NetworkManager::setUrlFirst()
{
switch (__m_iChannel)
{
case MC_0:
break;
case MC_T:
__m_sUrlFirst = LOCATION_TEST;
break;
case MC_G:
break;
default:
break;
}
}
//设置服务端地址;
void NetworkManager::setServerAddress(string addressStr)
{
__m_sUrlFirst = addressStr;
}
//设置回调类,及回调函数;
voidNetworkManager::setListenerAndCallfunND(Ref* Listener, SEL_CallFuncND CallFuns)
{
__m_pListener = Listener;
__m_cCallfuncND = CallFuns;
}
//支线程处理网络;
void NetworkManager::threadingSupportNetwork(void* data)
{
NetworkManager* p_This =(NetworkManager*)data;
//创建HttpRequest对象,这里new出来用于保存数据;
HttpRequest* request = new HttpRequest();
//设置请求业务地址URL;
request->setUrl(p_This->__m_sStorageUrl.c_str());
//设置请求方式;
request->setRequestType(HttpRequest::Type::GET);
//设置回调对象及回调函数;
request->setResponseCallback(CC_CALLBACK_2(NetworkManager::onHttpRequestCompleted,p_This));
//设置标识;
request->setTag("GETtest1");
//使用CCHttpClient单例发送请求;
HttpClient::getInstance()->send(request);
//调用release;
request->release();
}
//请求地址;
void NetworkManager::RequestUrlAddress(string addressStr)
{
//重置监听;
__m_tHttpState.m_bSucceed = false;
__m_tHttpState.m_bResolve = false;
__m_tHttpState.m_vResData = "";
__m_bThread = false;
GET_G_LOAD_S();
//监听支线程是否结束;
this->schedule(schedule_selector(NetworkManager::threadOver));
//存储地址,当网络不好的情况下,用于重复申请;
__m_sStorageUrl = __m_sUrlFirst +addressStr;
//执行支线程;
httpRequestBusiness();
}
//请求业务;
void NetworkManager::httpRequestBusiness()
{
//支线程;
thread t_Accep(threadingSupportNetwork,(void*)this);
//线程分离;
t_Accep.detach();
}
//网络回调;
void NetworkManager::onHttpRequestCompleted(HttpClient *sender, HttpResponse*response)
{
if (!response)
{
return;
}
//网络状况;
long statusCode =response->getResponseCode();
log("response code: %ld",statusCode);
//判断是否成功;
if (!response->isSucceed())
{//失败;
log("response failed");
//错误信息;
log("error buffer: %s",response->getErrorBuffer());
//返回逻辑1;
ReturnLogic(1);
return;
}
//连接服务端成功;
__m_tHttpState.m_bSucceed = true;
//获取请求数据;
std::vector *buffer =response->getResponseData();
std::string aastring;
int ii = 0;
int iii = buffer->size();
for (; ii < iii; ii++) {
aastring.push_back(buffer->at(ii));
}
//log("Data = %s",aastring.c_str());
//请求引用计数不能为2;
if(response->getHttpRequest()->getReferenceCount() != 2)
{
log("request ref count not 2,is %d", response->getHttpRequest()->getReferenceCount());
}
//效验数据;
efficacyData(aastring);
}
//效验数据;
void NetworkManager::efficacyData(stringsdata)
{
//根据与服务端的协议,自己根据实际情况进行效验;
rapidjson::Document data_Json;
data_Json.Parse<0>(sdata.c_str());
if (data_Json.HasParseError())
{//解析错误;
log("GetParseError%s\n", data_Json.GetParseError());
//返回逻辑1;
ReturnLogic(2);
__m_tHttpState.m_bResolve = false;
__m_tHttpState.m_vResData ="";
}
else
{//解析正确;
__m_tHttpState.m_bResolve = true;
__m_tHttpState.m_vResData = sdata;
}
//线程结束;
__m_bThread = true;
}
//支线程结果监听;
void NetworkManager::threadOver(float dt)
{
if (__m_bThread)
{//如果线程结束;
//线程开关重置;
__m_bThread = false;
if (__m_tHttpState.m_bSucceed)
{//如果连接服务器成功;
if(__m_tHttpState.m_bResolve)
{//如果数据解析正确;
if(__m_tHttpState.m_vResData.size() > 0)
{//如果数据不为0;
if(__m_pListener && __m_cCallfuncND)
{
(__m_pListener->*__m_cCallfuncND)((Node*)this,&__m_tHttpState);
}
}
}
}
//关闭计时器;
this->unschedule(schedule_selector(NetworkManager::threadOver));
}
}
```
创建好了,对于NetWork库的使用,大家可以去问度娘,上面有很详细的教程,我就不班门弄斧了,因为我觉得比人讲的比我能更深刻一些。(好自卑啊)
给大家推荐一篇文章,我觉得比较适合同学们做了解
http://blog.csdn.net/gf771115/article/details/24605155
然后将公用头文件将上对网络管理器的使用
#ifndef __PUBLIC_HEADER_FILES_H__
#define __PUBLIC_HEADER_FILES_H__
#include"uimanager/UIManager.h"
#include"ResourcePath.h"
#include"json/rapidjson.h"
#include"json/document.h"
#include"NetworkManager.h"
enum Layer_Name
{
LN_TEST_1 = 0,
LN_TEST_2,
LN_LOGO,
LN_MENU,
LN_CONFIG,
LN_GAME,
LN_TIPS,
};
#endif //__PUBLIC_HEADER_FILES_H__
```
那么我就讲讲详细的网络管理器这块
//构造函数;
NetworkManager::NetworkManager()
{
//设置超时;
HttpClient::getInstance()->setTimeoutForRead(20);
}
//析构函数;
NetworkManager::~NetworkManager()
{
//退出时必须调用destroyInstance,否则程序崩溃;
HttpClient::getInstance()->destroyInstance();
}
//静态创建网络管理器;
NetworkManager* NetworkManager::getNewworkManager()
{
if (myNewwork == nullptr)
{
myNewwork = new NetworkManager();
//初始化数据;
myNewwork->initNetworkData();
}
return myNewwork;
}
```
首先我单例了网络管理器,以便于使用,然后并宏定义,方便调用和预处理。然后在构造函数里对于超时时间做了下设置,一般游戏的超时连接都是20秒,但是为什么20秒,这个就需要自己思考了。
//设置网址首地址;
voidNetworkManager::setUrlFirst()
{
switch (__m_iChannel)
{
case MC_0:
break;
case MC_T:
__m_sUrlFirst = LOCATION_TEST;
break;
case MC_G:
break;
default:
break;
}
}
```
然后在析构的时候将资源是否掉。单例的时候做了一些数据的初始化,这个地方一般都是有测试服务器,外网测试服务器等,这里做了个渠道区分,也是为了以后分渠道准备的,因为以后分区后地址会很多。
//设置服务端地址;
void NetworkManager::setServerAddress(string addressStr)
{
__m_sUrlFirst = addressStr;
}
//设置回调类,及回调函数;
void NetworkManager::setListenerAndCallfunND(Ref* Listener, SEL_CallFuncND CallFuns)
{
__m_pListener = Listener;
__m_cCallfuncND = CallFuns;
}
//请求地址;
void NetworkManager::RequestUrlAddress(string addressStr)
{
//重置监听;
__m_tHttpState.m_bSucceed = false;
__m_tHttpState.m_bResolve = false;
__m_tHttpState.m_vResData = "";
__m_bThread = false;
GET_G_LOAD_S();
//监听支线程是否结束;
this->schedule(schedule_selector(NetworkManager::threadOver));
//存储地址,当网络不好的情况下,用于重复申请;
__m_sStorageUrl = __m_sUrlFirst +addressStr;
//执行支线程;
httpRequestBusiness();
}
//请求业务;
void NetworkManager::httpRequestBusiness()
{
//支线程;
thread t_Accep(threadingSupportNetwork,(void*)this);
//线程分离;
t_Accep.detach();
}
```
然后将管理器的一般配置函数写好,基本上就完成了基础搭建。
然后将网络请求委托给支线程进行处理
//支线程处理网络;
voidNetworkManager::threadingSupportNetwork(void* data)
{
NetworkManager* p_This =(NetworkManager*)data;
//创建HttpRequest对象,这里new出来用于保存数据;
HttpRequest* request = new HttpRequest();
//设置请求业务地址URL;
request->setUrl(p_This->__m_sStorageUrl.c_str());
//设置请求方式;
request->setRequestType(HttpRequest::Type::GET);
//设置回调对象及回调函数;
request->setResponseCallback(CC_CALLBACK_2(NetworkManager::onHttpRequestCompleted,p_This));
//设置标识;
request->setTag("GETtest1");
//使用CCHttpClient单例发送请求;
HttpClient::getInstance()->send(request);
//调用release;
request->release();
}
//网络回调;
voidNetworkManager::onHttpRequestCompleted(HttpClient *sender, HttpResponse*response)
{
if (!response)
{
return;
}
//网络状况;
long statusCode = response->getResponseCode();
log("response code: %ld",statusCode);
//判断是否成功;
if (!response->isSucceed())
{//失败;
log("response failed");
//错误信息;
log("error buffer: %s",response->getErrorBuffer());
//返回逻辑1;
ReturnLogic(1);
return;
}
//连接服务端成功;
__m_tHttpState.m_bSucceed = true;
//获取请求数据;
std::vector *buffer =response->getResponseData();
std::string aastring;
int ii = 0;
int iii = buffer->size();
for (; ii < iii; ii++) {
aastring.push_back(buffer->at(ii));
}
//log("Data = %s",aastring.c_str());
//请求引用计数不能为2;
if(response->getHttpRequest()->getReferenceCount() != 2)
{
log("request ref count not 2,is %d", response->getHttpRequest()->getReferenceCount());
}
//效验数据;
efficacyData(aastring);
}
```
在response->getResponseCode()函数里会返回一些状态码,在网络回调中,我们必须要知道的一些网络基础知识,我想404大家都应该知道是什么吧?但是其他的呢?我将一些基本的状态码贴出来,以供大家参考。
这类状态代码表明服务器成功地接受了客户端请求。
200 - 确定。客户端请求已成功。
201 - 已创建。
202 - 已接受。
203 - 非权威性信息。
204 - 无内容。
205 - 重置内容。
206 - 部分内容。
207 - 多状态(WebDAV)。
3xx - 重定向
发生错误,客户端似乎有问题。例如,客户端请求不存在的页面,客户端未提供有效的身份验证信息。
400 - 错误的请求。
401 - 访问被拒绝。
401.1 - 登录失败。
401.2 - 服务器配置导致登录失败。
401.3 - 由于 ACL 对资源的限制而未获得授权。
401.4 - 筛选器授权失败。
401.5 - ISAPI/CGI应用程序授权失败。
401.7 – 由 Web 服务器上的 URL 验证策略拒绝访问。这个错误代码为 IIS 6.0 所专用。
403 - 禁止访问:IIS 定义了几个不同的 403 错误,用于指示更为具体的错误原因:
403.1 - 执行访问被禁止。
403.2 - 读访问被禁止。
403.3 - 写访问被禁止。
403.4 - 要求 SSL。
403.5 - 要求 SSL 128。
403.6 - IP 地址被拒绝。
403.7 - 要求客户端证书。
403.8 - 站点访问被拒绝。
403.9 - 用户数过多。
403.10 - 配置无效。
403.11 - 密码更改。
403.12 - 拒绝访问映射表。
403.13 - 客户端证书被吊销。
403.14 - 拒绝目录列表。
403.15 - 超出客户端访问许可。
403.16 - 客户端证书不受信任或无效。
403.17 - 客户端证书已过期或尚未生效。
403.18 - 在当前的应用程序池中不能执行所请求的 URL。这个错误代码为 IIS 6.0 所专用。
403.19 - 不能为这个应用程序池中的客户端执行 CGI。这个错误代码为 IIS 6.0 所专用。
403.20 - Passport登录失败。这个错误代码为 IIS 6.0 所专用。
404 - 未找到。
404.0 -(无) – 没有找到文件或目录。
404.1 - 无法通过请求的端口访问网站。
404.2 - Web 服务扩展锁定策略阻止本请求。
404.3 - MIME 映射策略阻止了此请求。
405 - 用来访问本页面的HTTP 谓词不被允许(方法不被允许)
406 - 客户端浏览器不接受所请求页面的 MIME 类型。
407 - 要求进行代理身份验证。
412 - 前提条件失败。
413 – 请求实体太大。
414 - 请求 URI 太长。
415 – 不支持的媒体类型。
416 – 无法满足请求的范围。
417 – 执行失败。
423 – 锁定的错误。
5xx - 服务器错误
服务器由于遇到错误而不能完成该请求。
500 - 内部服务器错误。
500.12 - 应用程序正忙于在Web 服务器上重新启动。
500.13 - Web 服务器太忙。
500.15 - 不允许直接请求Global.asa。
500.16 – UNC 授权凭据不正确。这个错误代码为 IIS 6.0 所专用。
500.18 – 无法打开 URL 授权存储库。这个错误代码为 IIS 6.0 所专用。
500.19 - 此文件的数据在元数据库中配置不正确。
500.100 - 内部 ASP 错误。
501 - 页眉值指定了未实现的配置。
502 - Web 服务器用作网关或代理服务器时收到了无效响应。
502.1 - CGI 应用程序超时。
502.2 - CGI 应用程序出错。
503 - 服务不可用。这个错误代码为 IIS 6.0 所专用。
504 - 网关超时。
505 - HTTP 版本不受支持。
其实一般我们只需要判断200就好了,其他原因我们可以自己写个网络判断模块进行处理就好了
当我们接收到数据后,这里面还有个重要的步骤,就是数据效验!
客户端一定要对数据进行有效的效验,才能保证数据的完整性与安全性。一般数据效验可以跟服务端按照规定的协议进行效验,在代码里我就不过多的去描述了。
然后我们基本的网络管理器就搭建成功了!!
现在还需要什么?是的,提示层!如果我们网络管理器对网络处理及数据解析发生了错误怎么办?肯定不能卡住啊,所以一般情况下,我们会重新请求或执行其他步骤!
那么我们开始创建提示层UI_Tpis类,同样在CocosStudio里也创建一份
#ifndef _UI_TIPS_H_
#define _UI_TIPS_H_
#include"PublicHeaderFiles.h"
class UI_Tips:public BaseLayer
{
public:
//重载创建;
static UI_Tips * create(const int type);
//初始化;
virtual bool init();
//创建;
CREATE_FUNC(UI_Tips);
//重载;
virtual void showUI();
//显示;
void showTipsUI();
//菜单事件;
void Menu_Event(Ref *pSender,Widget::TouchEventType type);
//读取数据;
void readData(const int type);
public:
//studio;
Layer* m_pUiLayer;
//布局文件;
Layout* m_pWidget;
//类型;
int m_iTallType;
};
#endif //_UI_TIPS_H_
```
.cpp
#include"UI_Tips.h"
//重载创建;
UI_Tips *UI_Tips::create(const int type)
{
UI_Tips *ret = new UI_Tips();
if (ret && ret->init())
{
ret->autorelease();
ret->readData(type);
return ret;
}
else
{
CC_SAFE_DELETE(ret);
return nullptr;
}
}
//初始化;
bool UI_Tips::init()
{
if (!Layer::init())
{
return false;
}
m_pUiLayer = nullptr;
m_pWidget = nullptr;
//继承BaseLayer,负责动画索引类型;
m_iActionIndex = GAI_NULL;
return true;
}
//读取数据;
void UI_Tips::readData(const int type)
{
m_iTallType = type;
}
//重载;
void UI_Tips::showUI()
{
showTipsUI();
}
//显示;
void UI_Tips::showTipsUI()
{
if (m_pUiLayer == nullptr)
{
m_pUiLayer = Layer::create();
this->addChild(m_pUiLayer, 3,0);
auto maskLayer =LayerColor::create(Color4B(0, 0, 0, 160));
this->addChild(maskLayer, 0);
}
m_pWidget =static_cast(GUIReader::getInstance()->widgetFromJsonFile(RES_UI_TIPS));
m_pUiLayer->addChild(m_pWidget);
auto m_pConfig =static_cast(Helper::seekWidgetByName(m_pWidget,"Button_Enter"));
m_pConfig->addTouchEventListener(CC_CALLBACK_2(UI_Tips::Menu_Event,this));
auto m_pImgBG =static_cast(Helper::seekWidgetByName(m_pWidget,"Image_BG"));
string tallStr = "";
switch (m_iTallType)
{
case 0:
break;
case 1:
break;
case 2:
tallStr = "GetParseErrorExpect either an object or array at root";
break;
default:
break;
}
auto _label = Label::create();
_label->setDimensions(210, 160);
_label->setAlignment(TextHAlignment::CENTER,TextVAlignment::CENTER);
_label->setSystemFontSize(32);
_label->setString(tallStr.c_str());
_label->setPosition(Vec2(m_pImgBG->getContentSize().width/ 2+100, m_pImgBG->getContentSize().height / 2-10));
_label->setColor(ccBLACK);
m_pImgBG->addChild(_label);
}
//菜单事件;
void UI_Tips::Menu_Event(Ref *pSender, Widget::TouchEventType type)
{
switch (type)
{
//触摸事件;
case Widget::TouchEventType::BEGAN:
break;
//移动事件;
case Widget::TouchEventType::MOVED:
break;
//抬起事件;
case Widget::TouchEventType::ENDED:
//重新请求业务;
GET_G_NET_RR();
this->runAction(Sequence::create(
DelayTime::create(0.2f),
RemoveSelf::create(true),
nullptr));
break;
//越界事件;
case Widget::TouchEventType::CANCELED:
break;
default:
break;
}
}
```
接下来我们需要修改下管理器GameMain的函数就好了
将UI管理器与网络管理器代码封装下
//设置UI管理器;
void GameMain::setUIManager()
{
//设置UI管理器与管理器连接;
GET_T_SM(this);
//逻辑回调地址;
SEL_CallFuncND t_Logic =callfuncND_selector(GameMain::setUILayerLogic);
//绘制回调地址;
SEL_CallFuncND t_Drwa = callfuncND_selector(GameMain::setUILayerDraw);
//设置UI管理器与管理器逻辑连接;
GET_G_LOGIC(t_Logic, t_Drwa);
//加载UI管理器;
this->addChild(GET_G_UI(), 0);
//创建Loading层;
UI_Loading* loadingLayer =UI_Loading::create();
//设置Loading层;
GET_G_UI()->setLoadIngLayer(loadingLayer);
loadingLayer->showUI();
//设置业务 执行逻辑——LN_LOGO;
setUILayerLogic(nullptr, (void*)LN_LOGO);
}
//设置网络管理器;
void GameMain::setNetworkManager()
{
//管理器加载;
this->addChild(GET_G_NET(), -1);
//设置错误返回地址;
GET_G_NET_LOGIC(this,callfuncND_selector(GameMain::setNetWorkLogic));
//设置回调类,及回调函数;
//哪个类要执行业务,就将这个函数写到哪个类里;
//由于是测试,我将回调写在了管理器里;
GET_G_NET_LISTENER(this,callfuncND_selector(GameMain::setNetWorkLogicRes));
//请求业务;
//GET_G_NET_REQUEST("");
}
```
然后给网络管理器 2个回调地址
网络回调 一般情况都是错误提示,可以在里面写提示框
业务回调 是我们具体哪个类 执行了网络业务 然后对调给哪个类
//网络回调;
void GameMain::setNetWorkLogic(Node* pSender, void* cIndex)
{
//关闭Loading;
GET_G_LOAD_E();
//返回错误类型;
int m_iIndex = (int)cIndex;
//根据返回错误信息类型,进行创建;
UI_Tips* m_pTips =UI_Tips::create(m_iIndex);
this->addChild(m_pTips, 1);
m_pTips->showUI();
}
//业务回调;
void GameMain::setNetWorkLogicRes(Node* pSender, void* cIndex)
{
HttpState* temp = (HttpState*)(cIndex);
log("%s",temp->m_vResData.c_str());
}
```
然后将业务申请写到Menu类的Button对调函数里
//菜单事件;
void UI_Menu::Menu_Event(Ref *pSender, Widget::TouchEventType type)
{
switch (type)
{
case Widget::TouchEventType::BEGAN:
break;
case Widget::TouchEventType::MOVED:
break;
case Widget::TouchEventType::ENDED:
{
int tag =((Button*)pSender)->getTag();
switch (tag)
{
case 10:
log("Config");
{
//由于Config类是属于Menu下的,所以我将Config加载在Menu上;
UI_Config*temp = UI_Config::create();
this->addChild(temp,4);
//这里是为了测试返回逻辑的函数;
temp->LoadUILogic(this,callfuncND_selector(UI_Menu::TestRes));
temp->showUI();
}
break;
default:
log("Button =%d", tag);
//请求业务;
GET_G_NET_REQUEST("");
break;
}
}
break;
case Widget::TouchEventType::CANCELED:
break;
default:
break;
}
}
```
OK,那么我们运行看下!
为什么会报错误呢?这是因为,我写的请求地址是百度,由于百度给反馈的数据,并不是一个有效的Json数据,所以在数据解析的时候出错了,我们看下代码。
//效验数据;
void NetworkManager::efficacyData(string sdata)
{
//根据与服务端的协议,自己根据实际情况进行效验;
rapidjson::Document data_Json;
data_Json.Parse<0>(sdata.c_str());
if (data_Json.HasParseError())
{//解析错误;
log("GetParseError%s\n", data_Json.GetParseError());
//返回逻辑1;
ReturnLogic(2);
__m_tHttpState.m_bResolve = false;
__m_tHttpState.m_vResData ="";
}
else
{//解析正确;
__m_tHttpState.m_bResolve = true;
__m_tHttpState.m_vResData = sdata;
}
//线程结束;
__m_bThread = true;
}
```
在数据解析错误的时候 我返回了逻辑2,那么我们看下提示层函数
string tallStr ="";
switch (m_iTallType)
{
case 0:
break;
case 1:
break;
case 2:
tallStr = "GetParseErrorExpect either an object or array at root";
break;
default:
break;
}
```
OK!网络这块真的很大,也是非常重要的位置,下一章我们将会针对数据类,进行一节大概的了解,我尽可能将,数据管理器及数据库管理器一起讲解下。
那么,我们下一节再见!
讲的有点粗了,不够详细
发现源码里有点问题…
楼主 有 发到博客 上吗= =。。。这论坛的代码 高亮 太蛋疼了。。。根本 就没亮。。。
