CCHttpRequest 本身是一个CCObject 对象, 用于lua的create函数 默认会retain request对象一次,因此需要在lua的callback函数里面处理结束request之后,需要release对象否则会内存泄露。
实际的引用计数变化的过程如下:
new 引用计数 = 1
autorelease 引用计数先变成2 再变成1 , 将对象加入自动释放池子里面之后,对象引用计数会+1, 接着会调用对象的release方法,对象引用计数又减去1
retain 引用计数变成 2
start 开始http请求,对象加入schedule 的列表里面 引用计数+1 引用计数变成3
update 过程中,到下一个update循环的时候,对象的引用计数会减去1,因为自动释放池子release了这个对象,这时候引用计数变成2
http请求处理结束,update函数里面检测结束,取消schedule 更新,但是因为当前在函数体内,所以不会立即release掉request对象,而是等待本次回合结束的时候再release对象
http请求结束,在callback函数里面release 掉对象,引用计数-1 变成 1
在本次更新回合结束,schedule模块,将标记删除的对象的引用计数-1, 引用计数 = 0 对象被删除掉。
#include "network/CCHttpRequest.h"
#include "network/CCHttpRequest_impl.h"
#include "cocos2d.h"
#include "CCLuaEngine.h"
using namespace cocos2d;
NS_CC_EXT_BEGIN
CCHttpRequest* CCHttpRequest::createWithUrl(CCHttpRequestDelegate* delegate,
const char* url,
CCHttpRequestMethod method,
bool isAutoReleaseOnFinish)
{
CCHttpRequest* request = new CCHttpRequest(delegate, url, method, isAutoReleaseOnFinish);
request->initHttpRequest();
request->autorelease();
if (isAutoReleaseOnFinish)
{
request->retain();
}
return request;
}
CCHttpRequest* CCHttpRequest::createWithUrlLua(int nHandler, const char* url, bool isGet)
{
CCHttpRequest* request = new CCHttpRequest(NULL, url, isGet?CCHttpRequestMethodGET:CCHttpRequestMethodPOST, true);
request->m_luaHandler = nHandler;
request->initHttpRequest();
request->autorelease();
request->retain();
CCLog("request count is? %d", request->retainCount());
return request;
}
bool CCHttpRequest::initHttpRequest(void)
{
m_request = new CCHttpRequest_impl(m_url.c_str(), m_method);
return true;
}
CCHttpRequest::~CCHttpRequest(void)
{
delete (CCHttpRequest_impl*)m_request;
}
void CCHttpRequest::addRequestHeader(const char* key, const char* value)
{
if (key && value)
{
((CCHttpRequest_impl*)m_request)->addRequestHeader(key, value);
}
}
void CCHttpRequest::addPostValue(const char* key, const char* value)
{
if (key && value)
{
((CCHttpRequest_impl*)m_request)->addPostValue(key, value);
}
}
void CCHttpRequest::setPostData(const char* data)
{
if (data)
{
((CCHttpRequest_impl*)m_request)->setPostData(data);
}
}
void CCHttpRequest::setTimeout(float timeout)
{
((CCHttpRequest_impl*)m_request)->setTimeout(timeout);
}
bool CCHttpRequest::getIsInProgress(void)
{
return ((CCHttpRequest_impl*)m_request)->getIsInProgress();
}
void CCHttpRequest::start(bool isCached)
{
CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);
if (((CCHttpRequest_impl*)m_request)->start())
{
CCDirector::sharedDirector()->getScheduler()->scheduleUpdateForTarget(this, 0, false);
}
}
void CCHttpRequest::cancel(void)
{
CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);
((CCHttpRequest_impl*)m_request)->cancel();
}
void CCHttpRequest::clearDelegatesAndCancel(void)
{
m_delegate = NULL;
cancel();
}
int CCHttpRequest::getResponseStatusCode(void) {
return ((CCHttpRequest_impl*)m_request)->getResponseStatusCode();
}
const char* CCHttpRequest::getResponseString(void)
{
return ((CCHttpRequest_impl*)m_request)->getResposeString().c_str();
}
const void* CCHttpRequest::getResponseData(int* dataLength)
{
return ((CCHttpRequest_impl*)m_request)->getResponseData();
}
int CCHttpRequest::getResponseDataLength()
{
return ((CCHttpRequest_impl*)m_request)->getResponseDataLength();
}
CCHttpRequestError CCHttpRequest::getErrorCode(void)
{
return ((CCHttpRequest_impl*)m_request)->getErrorCode();
}
const char* CCHttpRequest::getErrorMessage(void)
{
return ((CCHttpRequest_impl*)m_request)->getErrorMessage();
}
void CCHttpRequest::update(float dt)
{
CCLog("update Request state %d", retainCount());
CCHttpRequest_impl* request = (CCHttpRequest_impl*)m_request;
if (!request || !request->getIsInProgress())
{
CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);
}
if (request->getIsCompleted())
{
if (m_delegate) m_delegate->requestFinished(this);
if (m_luaHandler)
{
bool isSuc = (request->getErrorCode()==CCHttpRequestErrorNone);
CCLuaEngine* engine = CCLuaEngine::defaultEngine();
engine->getLuaStack()->clean();
engine->getLuaStack()->pushBoolean(isSuc);
engine->getLuaStack()->executeFunctionByHandler(m_luaHandler, 1);
CCLog("afterHandler retainCount %d", retainCount());
/*
cocos2d::CCLuaValueDict dict;
dict["name"] = cocos2d::CCLuaValue::stringValue("completed");
dict["request"] = cocos2d::CCLuaValue::ccobjectValue(this, "CCHttpRequest");
cocos2d::CCLuaEngine* engine = cocos2d::CCLuaEngine::defaultEngine();
engine->cleanStack();
engine->pushCCLuaValueDict(dict);
engine->executeFunctionByHandler(m_luaHandler, 1);
*/
}
}
else if (request->getIsCancelled())
{
if (m_delegate) m_delegate->requestFailed(this);
if (m_luaHandler)
{
CCLuaEngine* engine = CCLuaEngine::defaultEngine();
engine->getLuaStack()->clean();
engine->getLuaStack()->pushBoolean(false);
engine->getLuaStack()->executeFunctionByHandler(m_luaHandler, 1);
/*
cocos2d::CCLuaValueDict dict;
dict["name"] = cocos2d::CCLuaValue::stringValue("failed");
dict["request"] = cocos2d::CCLuaValue::ccobjectValue(this, "CCHttpRequest");
cocos2d::CCLuaEngine* engine = cocos2d::CCLuaEngine::defaultEngine();
engine->cleanStack();
engine->pushCCLuaValueDict(dict);
engine->executeFunctionByHandler(m_luaHandler, 1);
*/
}
}
}
NS_CC_EXT_END