问题描述
在Android包下,使用了第三方SDK登录,在切出去登录成功后,在SDK的回调中使用runOnGLThread线程回调到TS代码中。
appActivity.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxJavascriptJavaBridge.evalString("SystemBridge.OnLoginSuccess(\""+ accessToken + "\",\"" + userId+"\")");
}
});
然后,在TS代码中,使用了XMLHttpRequest的post协议异步请求消息向服务器登录。
public static OnLoginSuccess(token: string, id: string) {
let postData = {
"token":token,
"id":id
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// TODO 处理登录成功
}
}
};
xhr.open("POST", "登录服务器Url", true);
xhr.timeout = 10000;
xhr.ontimeout = () => {
// TODO 处理登录超时
}
xhr.send(postData);
xhr.onerror = () => {
// TODO 处理登录错误
}
}
最后返回的结果是 刚发送数据同一帧就收到了ontimeout的回调,然后部分手机还会出现崩溃情况。
分析
XMLHttpRequest 的异步逻辑类似于setTimeout,setTimeout 和 XMLHttpRequest.onreadystatechange 用的都是同一个 Event Queue,唯一区别是 setTimeout 是定时器线程往队列里压,XMLHttpRequest.onreadystatechange 是 HTTP 异步请求线程往队列里压,其逻辑就要看CocosCreator的Main Loop了。可能原因是应用从别的程序中切换过来时,导致Main Loop回调出了点问题。
解决办法
就是在整个post时,用schedule做一个延迟回调。等到Event Queue队列循环正常后再调用post函数就可以了。
public static OnLoginSuccess(token: string, id: string) {
Timer.scheduleOnce(() => {
let postData = {
"token":token,
"id":id
}
...
其他代码
}, 0.1)
}