cocos2dx lua —— Http请求总结与实战(封装)
今天的主题是关于cocos2dx lua实现短链接网络请求,使用Http实现基本的服务器网络数据获取,关于长链接(socket后续文件或者遇到需要的时候回特别实现与处理)
关于Http这里就不多做介绍了,不过,作为一个程序员,网络请求是开发中最多也是最重要的一环节,这里比较建议,搞懂http的整个请求流程!
在有了基本的Lua知识和cocos2dx lua基本的了解和学习之后,我有了一个初步的cocos2dx lua开发常识,然后就开始在上面实现基本的界面,并根据界面操作请求和响应数据!
入口场景
在main中初始化场景中必要的UI.
创建一个背景图片和一个按钮,实现点击按钮跳转到另外一个场景,进行网络请求和数据获取
--- @class MainScene
local MainScene = class("MainScene",cc.load("mvc").ViewBase)
—onEnter
function MainScene:onEnter()
print("onEnter")
end
—createStaticButton 通用创建按钮方法
—@param node table
—@param imageName table
—@param x table
—@param y table
—@param callBack table
local function createStaticButton(node, imageName, x, y, callBack)
local btn = ccui.Button:create(imageName, imageName)
btn:move(x, y)
btn:addClickEventListener(callBack)
btn:addTo(node)
end
-----onCreate
function MainScene:onCreate()
-- 初始化背景
display.newSprite("HelloWorld.png")
:move(display.center)
:addTo(self)
-- 初始化按钮
createStaticButton(self, "button_start.png", display.cx, display.cy-150, function ()
self:getApp():enterScene("ApiRequest")
end)
end
return MainScene
网络应用场景(ApiRequest)
然后开始处理跳转之后的ApiRequest,和相关请求逻辑,这里主要是使用我们封装好的CocosRequest实现基本上的请求逻辑,然后拿到数据之后我们就可以根据实际UI和具体业务逻辑做处理
注意
测试的时候,将local url = “https://xxxx?cmd=501001&uid=628941&novelid=3782"中的值换成自己的地址就可以
require "json"
local CocosRequest = require "app.CocosRequest"
— @class ApiRequest
local ApiRequest = class("ApiRequest", cc.load("mvc").ViewBase)
----local MainScene = class("MainScene", function() return display.newScene("MainScene") end)
—onEnter
function ApiRequest:onEnter()
print("onEnter")
end
-----onCreate
function ApiRequest:onCreate()
----------------------- 创建自定义事件 start
local function eventCustomListener1(event)
local str = "response: "..event._usedata
--labelStatusCode:setString(str)
-- 如果返回的是 json 数据,这里解析
local data = json.decode(event._usedata)
table.foreach(data,
function(key, var)
print("-----"..key)
table.foreach(var,
function(a, b)
print(a.."-"..b)
end)
end)
end
local listener1 = cc.EventListenerCustom:create("customEvent1",eventCustomListener1)
cc.Director:getInstance():setNotificationNode(cc.Node:create())
local eventDispatcher = cc.Director:getInstance():getNotificationNode():getEventDispatcher()
eventDispatcher:addEventListenerWithFixedPriority(listener1, 6)
-- 将事件分配器赋值到CocosRequest.eventDispatcher
-- 用来在http请求返回的回调函数中使用,因为回调函数是在异步线程中执行,必须用自定义事件更新ui线程数据
local tmpHttp = CocosRequest:getInstance()
tmpHttp.eventDispatcher = eventDispatcher
----------------------- 创建自定义事件 end
local tmp = CocosRequest:getInstance()
local function callback(xhr)
local event = cc.EventCustom:new("customEvent1")
event._usedata = xhr.response
eventDispatcher:dispatchEvent(event)
print("post callback code = "..xhr.statusText)
end
local type = tmp.POST
local url = "https://xxxx?cmd=501001&uid=628941&novelid=3782"
local dataPost = {}
dataPost.data = "hello"
dataPost.aaa = "world"
dataPost.bbb = "yang"
tmp:send(type, url, dataPost, callback)
end
return ApiRequest
网络请求封装(CocosRequest)
最后才是我们的重头戏,CocosRequest是直接使用cocos2dx lua提供的XMLHttpRequest实现,其实就是做了一套逻辑,具体细节可以根据项目调整(此处已经测试通过,可直接拷贝使用)
require "json"
CocosRequest = {}
CocosRequest.__index = CocosRequest
CocosRequest.instance = nil
CocosRequest.callback = nil
CocosRequest.POST = "POST"
CocosRequest.GET = "GET"
function CocosRequest:new()
local self = {}
setmetatable(self,CocosRequest)
return self
end
function CocosRequest:getInstance()
if nil == self.instance then
self.instance = self:new()
end
return self.instance
end
-- 数据转换,将请求数据由 table 型转换成 string,参数:table
function CocosRequest:dataParse(data)
if "table" ~= type(data) then
print("data is not a table")
return nil
end
local tmp = {}
for key, value in pairs(data) do
table.insert(tmp,key.."="..value)
end
local newData = ""
for i=1,#tmp do
newData = newData..tostring(tmp[i])
if i<#tmp then
newData = newData.."&&"
end
end
print("------- name is "..newData)
return newData
end
-- 发送数据,参数:string,string,table
function CocosRequest:send(type, url, data, callback)
local xhr = cc.XMLHttpRequest:new() --new 一个http request 实例
self.callback = callback --设置需要执行的函数
local newData = self:dataParse(data)
if nil == newData or "" == newData then
return
end
-- response回调函数
local function responseCallback()
print("CocosRequest - "..xhr.response)
if nil ~= self.callback then
self.callback(xhr)
else
print("callback is nil")
end
end
-- 设置返回值类型及回调函数
xhr.responseType = cc.XMLHTTPREQUEST_RESPONSE_STRING
xhr:registerScriptHandler(responseCallback)
-- 请求方式判断
if self.POST == type then
xhr:open(self.POST, url)
xhr:registerScriptHandler(responseCallback)
xhr:send(newData)
elseif self.GET == type then
xhr:open(self.GET, url.."?"..newData)
xhr:send()
else
print("ERROR : type only can be "Post" or "GET"")
end
end
---------------------
return CocosRequest
由于在Web中使用XMLHTTPRequest对象发出HTTP请求很普遍,Cocos2dx Lua对其进行了移植,可以在 Cocos2 d-x LumP中使用 XMLHTTPRequest对象
XMLHTTPRequest对象中几个常用的函数和属性如下
- (1)open(),与服务器连接,创建新的请求
- (2)send(),向服务器发送请求
- (3)abort(),退出当前请求
- (4)readyState属性,提供当前请求的就绪状态,其中4表示准备就绪
- (5)tatus属性,提供当前HTTP请求状态码,其中200表示成功请求
- (6)respomseText属性,服务器返回的请求响应
- (7) onreadystatechange属性。设置回调函数,当服务器处理完请求后就会自动调用该
函数。
其中open和send函数,以及onreadystatechange属性是HTTP请求的关键。open函
数有以下5个参数可以使用
- (1) request-type:发送请求的类型。典型的值是GET或POST,也可以发送HEAD
请求 - (2) url:要请求连接的URL
- (3) asynch:如果希望使用异步连接则为true,否则为 false。该参数是可选的,默认为
- (4) username:如果需要身份验证,则可以在此指定用户名。该可选参数没有默认值
- (5) password:如果需要身份验证,则可以在此指定口令。该可选参数没有默认值。
服务器响应
下面是我们验证返回后的服务器数据(未做处理)
[
{
"code":1,
"msg":"操作成功",
"data":[
{
"novelid":"3782",
"uid":"628875",
"cid":"5",
"title":"零下记忆",
"cover":"http://xxxx/img/cb/2f/f1/cb2ff155bbda8387f4b8efe917c46cd3.jpg",
"scover":"http://xxxx/img/cb/2f/f1/cb2ff155bbda8387f4b8efe917c46cd3.jpg",
"shareimg":"http://xxxx/img/ed/68/e6/ed68e67f77841ac76be189f0a04aa030.jpg",
"intro":"",
"tags":"悬疑",
"reason":"",
"issingle":"1",
"sort":"0",
"hits":"0",
"reads":"18753",
"clues":20,
"likes":"1",
"unlikes":"0",
"cmts":"0",
"favs":"2",
"words":"18420",
"chapters":"35",
"pub_chapters":"35",
"chapter_index":"1",
"pubtime":"0",
"updatetime":"1539337440",
"addtime":"1534222233",
"resversion":"30",
"isuser":"0",
"status":"1",
"wstatus":"1",
"offsale":"0",
"chapterstatus":"-1",
"leadrole":{
"roleid":"8478",
"rolename":"炽念"
},
"cname":"推理",
"isnew":0,
"fatime":"8月14日",
"isreading":1,
"iscomplete":1,
"isfav":0,
"liketype":0,
"shareinfo":{
"type":1,
"title":"零下记忆",
"intro":"",
"img":"http://xxxx/img/ed/68/e6/ed68e67f77841ac76be189f0a04aa030.jpg",
"url":"http://xxxx/novel/startReading?novelid=3782&chl=jmt"
},
"userinfo":{
"uid":"628875",
"username":"writer10",
"nickname":"离经易道",
"headurl":"http://xxxx/headimg/bb/d3/b6/628875_1_bbd3b631717ad615f38a6670573a375c_300x300.jpg?v=1526708983",
"sex":"1",
"vtype":"0",
"regtype":"2",
"vname":"",
"vicon":"",
"isfollow":0
}
}
],
"cmd":501001,
"time":1539677040
}
]