CCHttpRequest 自己是一個CCObject 對象, 用於lua的create函數 默認會retain request對象一次,所以須要在lua的callback函數裏面處理結束request以後,須要release對象不然會內存泄露。 函數
實際的引用計數變化的過程以下: this
new 引用計數 = 1 lua
autorelease 引用計數先變成2 再變成1 , 將對象加入自動釋放池子裏面以後,對象引用計數會+1, 接着會調用對象的release方法,對象引用計數又減去1 url
retain 引用計數變成 2 spa
start 開始http請求,對象加入schedule 的列表裏面 引用計數+1 引用計數變成3 code
update 過程當中,到下一個update循環的時候,對象的引用計數會減去1,由於自動釋放池子release了這個對象,這時候引用計數變成2 對象
http請求處理結束,update函數裏面檢測結束,取消schedule 更新,可是由於當前在函數體內,因此不會當即release掉request對象,而是等待本次回合結束的時候再release對象 內存
http請求結束,在callback函數裏面release 掉對象,引用計數-1 變成 1 get
在本次更新回合結束,schedule模塊,將標記刪除的對象的引用計數-1, 引用計數 = 0 對象被刪除掉。 string
#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