Cocos网络访问——代理模式(2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/amy260231120/article/details/52133112

注:本文为作者原创,其中知识内容出自闪电终结者的视频课程

首先要强调一点,因为网络访问与Cocos的线程是不同的,网络访问需要自己的子线程(网络请求是需要时间的),所以在写代码时候无法将发生请求和请求数据写在一起,会导致无法请求到正确的数据,所以需要将请求数据之后调用的方法写在一个函数中,使用httpRequest类的setResponseCallback()函数来指定方法。

进入正题

上次把创建请求之类的都放在init()里,其实是不好的,如果会有多次请求,就需要创建多次HttpRequest对象

所以封装一个NetworkRequest类来实现

// NetworkRequest.hpp
#include <network/httpClient.h>
#include <string>
#include <functional>
class NetworkRequest {
    // url地址
    std::string url;
    // 表单数据,可有可无
    std::string postData;
    // 请求对象
    cocos2d::network::HttpRequest *request;
    // 数据请求之后调用的方法
    void networkRequestCallBack(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response);
public:
    NetworkRequest(const std::string &url, const std::string &postData = "");
    // 实例化一个对象时候,如果需要立刻执行网络请求,则把send()写入构造函数里
    virtual ~NetworkRequest();

    // 发生请求
    void send();
};
// NetworkRequest.cpp
#include "NetworkRequest.hpp"

NetworkRequest::NetworkRequest(const std::string &url, const std::string &postData): url(url), postData(postData) {
    // 把创建请求放入构造函数里,不需要每次都创建这个模型(request),只要每次send不同模型(request)就行
    request = new cocos2d::network::HttpRequest;
    request -> setUrl(url.c_str());
    if (postData == "") { 
        // 没有表单时候,只送数据即可
        request -> setRequestType(cocos2d::network::HttpRequest::Type::GET);
    } else {
        request -> setRequestType(cocos2d::network::HttpRequest::Type::POST);
        request -> setRequestData(postData.c_str(), postData.length());
    }
    // 设置这个请求与函数networkRequestCallBack连接,当收到服务器返回的数值时,调用该函数
    request -> setResponseCallback(CC_CALLBACK_2(NetworkRequest::networkRequestCallBack, this));
}


void NetworkRequest::send() {   
    cocos2d::network::HttpClient::getInstance() -> send(request);
    // 在真正使用完之后,request会被清除
    request -> release();
}
void NetworkRequest::networkRequestCallBack(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response){

}

NetworkRequest::~NetworkRequest() {}

现在唯一空着的是networkRequestCallBack函数,客户端需要对方法进行重构,在这里需要提供一个接口来完成该功能

  • 法一:成员变量的解决方法,不推荐
  • 法二:代理设计模式解决方法

代理模式

协议protocol:作为代理或者数据源要使用的方法

设计思路:
1.首先需要创建一个协议,如果要成为网络请求对象,则必须要实现协议中这个callBack方法

// 网络请求代理协议
class NetworkRequestDelegate {
public:
// 如果要成为网络请求对象,则必须要实现协议中这个callBack方法
// 声明为纯虚函数,因为此类是抽象类不能创建对象,考虑到继承的多态,用纯虚函数
    virtual void networkRequestCallBack(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response) = 0;
};

2.在networkRequest类中创建一个代理,这个代理遵守着NetworkRequestDelegate中的协议,代理可以在此类中调用遵守协议的方法

// 在networkRequest类中,声明一个代理对象(一个遵守协议的对象,此时就是TrandferTextScene)
    NetworkRequestDelegate *delegate;
// cpp文件中,实现networkRequestCallBack函数
void NetworkRequest::networkRequestCallBack(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response){
// 当代理不为空时,调用遵守的方法。
    if(delegate) {
        delegate -> networkRequestCallBack(sender, response);
    }
}

3.修改主场景的代码
主场景想要实现网络访问,必须遵守网络请求代理协议,实现networkRequestCallBack这个函数,

// TransferTestScene.hpp
class TransferTestScene : public cocos2d::Layer, public NetworkRequestDelegate { // 遵守网络请求代理协议
public:
    virtual bool init();
    static cocos2d::Scene *createScene();
    CREATE_FUNC(TransferTestScene);

private:
    void button1Click(cocos2d::Ref *sender, cocos2d::ui::Widget::TouchEventType type);
    cocos2d::Node *rootNode;
    // 遵守协议,实现该函数
    void networkRequestCallBack(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response);
};

在cpp中实现该函数(当请求数据时候的调用方法):

void TransferTestScene::networkRequestCallBack(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response) {
    if (!response -> isSucceed()) return;
    auto buffer = response -> getResponseData();
    std::string str(buffer -> begin(), buffer -> end());
    std::cout << str << std::endl;
}

4.修改客户端
创建一个NetworkRequest对象,!!然后把对象的代理设为自己,在发送内部已创建封装好的httpRequest对象。

            auto nq = new NetworkRequest("http://127.0.0.1/phptext.php","username=h11213&password=p231");
            即把NetworkRequest对象的代理设为自己,自己遵守着协议可以成为NetworkRequest对象的代理(决定着回调函数),
            nq -> delegate = this;
            nq -> send();

调试过程出现的问题

我用的编译器是xcode,
问题:在调试过程中出现连接问题
原因:构造函数的参数名写错了,导致在创建新的对象时候产生连接错误

这也许是个Xcode的Bug没有给提示,以后要注意了,这种小错误写代码时候就要保证没有。

猜你喜欢

转载自blog.csdn.net/amy260231120/article/details/52133112