Android在使用leancloud数据存储服务时出现下面这个错误:
cn.leancloud.AVException code=999 message=null
查阅了官方文档,并没有错误码为999的说明,于是查看了一下AVException.java源码,找到了999这个错误码的常量描述:
public class AVException extends Exception {
/**
* Error code indicating unknown reason.
*/
public static final int UNKNOWN = 999;
}
看意思就是个未知错误,如果就这么放弃那就不是个合格的程序员了,于是继续挖源码,看看什么情况下对应的code值会变成这个UNKNOWN,发现这个code值都是AVException这个类的构造方法里赋值的:
/**
* Construct a new AVException with a particular error code.
*
* @param theCode The error code to identify the type of exception.
* @param theMessage A message describing the error in more detail.
*/
public AVException(int theCode, String theMessage) {
super(theMessage);
this.code = theCode;
}
/**
* Construct a new AVException with an external cause.
*
* @param message A message describing the error in more detail.
* @param cause The cause of the error.
*/
public AVException(String message, Throwable cause) {
super(message, cause);
if (cause instanceof AVException) {
this.code = ((AVException) cause).getCode();
} else {
this.code = UNKNOWN;
}
}
/**
* Construct a new AVException with an external cause.
*
* @param cause The cause of the error.
*/
public AVException(Throwable cause) {
super(cause);
if (cause instanceof AVException) {
this.code = ((AVException) cause).getCode();
} else {
this.code = UNKNOWN;
}
}
于是把这几个构造方法都打上断点,看看是从哪里跳转过来的
于是来到了ErrorUtils.java这里:
public class ErrorUtils {
public static AVException propagateException(Throwable throwable) {
if (null == throwable) {
return null;
}
if (throwable instanceof HttpException) {
HttpException httpException = (HttpException) throwable;
if (null != httpException.response()) {
Response response = httpException.response();
if (null != response && null != response.errorBody()) {
try {
String content = response.errorBody().string();
AVException exception = ErrorUtils.propagateException(content);
return exception;
} catch (IOException ex) {
;
}
}
}
}
//是这里跳转过去的
return new AVException(AVException.UNKNOWN, throwable.getMessage());
};
}
分析这个方法后发现,会先判断当前的异常throwable是否HttpException,如果不是的话那标记错误码为:AVException.UNKNOWN,也就是我们之前看到的999,所以我们想要看到真正的异常信息,就需要断点这个方法传进来的throwable对象:
真正的异常信息是这个:android.os.NetworkOnMainThreadException
这是Android里面常见的异常信息,也就是不能在主线程里进行网络请求,于是回头看看写的LoanCload相关代码:
AVQuery<AVObject>("question")
.findInBackground()
.subscribe({
val datas = ArrayList<QuestionDataBean>()
for (data: AVObject in it) {
val tmp = QuestionDataBean()
tmp.question = data["question"] as String
tmp.answer = data["answer"] as String
datas.add(tmp)
}
mAdapter.initData(datas)
})
那个findInBackground的意思不就是异步获取数据吗?难道还要我自己在Rxjava里指定io线程?于是手动给它指定了io线程后果然就不报错了:
AVQuery<AVObject>("question")
.findInBackground()
.subscribeOn(Schedulers.io())//这里指定在io线程执行
.observeOn(AndroidSchedulers.mainThread())//返回结果在主线程执行
.subscribe({
val datas = ArrayList<QuestionDataBean>()
for (data: AVObject in it) {
val tmp = QuestionDataBean()
tmp.question = data["question"] as String
tmp.answer = data["answer"] as String
datas.add(tmp)
}
mAdapter.initData(datas)
})
总结:
1、都是leancloud的坑,文档不够详细,没有找到Android Rxjava相关示例
2、 findInBackground容易给人误导,让人以为已经指定了io线程异步执行
3、错误提示不够完善,throwable.getMessage()如果返回来的是null值,就应该再把其他异常信息保存起来,比如这次的android.os.NetworkOnMainThreadException异常