Closed hujxhed closed 6 months ago
我看网上这样写的:
inline fun <reified T> getObject(json: String): T = Gson().fromJson(json, T::class.java)
但是这个调用的时:
val result: UserInfo = Gson().fromJson(str)
不是用的T,用的是UserInfo,但是在这里我不能写死UserInfo,要不然只能解析Userinfo
我想要的是:
val result: T = Gson().fromJson(str)
能实现吗?
这样估计更适合你
open class BaseError : Serializable {
var code: String? = null
var msg: String? = null
}
class UserInfo : BaseError {
var userId : Int = 0
val name: String? = null
val age : Int = 0
}
此时不需要自定义解析器
RxHttp.postForm(AppConfig.URL_LOGIN)
.toObservable<UserInfo>()
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ userInfo ->
if (userInfo.code != null) {
//处理错误逻辑
} else {
}
Log.e(mTag, "userinfo=$userInfo")
}, { throwable ->
Log.e(mTag, "报错:" + throwable.toString())
})
当然,如果你想在自定义解析器里统一判断code,可以这么写
@Parser(name = "Response")
open class ResponseParser<T:BaseError> : TypeParser<T> {
protected constructor() : super()
constructor(type: Type) : super(type)
@Throws(IOException::class)
override fun onParse(response: okhttp3.Response): T {
val data: T = response.convert(types[0])
if (data.code != null) {
throw ParseException(data.code, data.msg, response)
}
return data
}
}
此时发请求
RxHttp.postForm(AppConfig.URL_LOGIN)
.toObservableResponse<UserInfo>()
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ userInfo ->
Log.e(mTag, "userinfo=$userInfo")
}, { throwable ->
//这里拿到code、msg处理错误逻辑,errorCode、errorMsg是Throwable对象的扩展字段,demo里可以找到
val code = throwable.errorCode
val msg = throwable.errorMsg
Log.e(mTag, "报错:" + throwable.toString())
})
感谢大神,你这个方法可以实现,但每个Bean都需要继承BaseError 我现在是这样做的,目前看没有问题,但不保证,你帮我看看有没有什么隐患?
@Parser(name = "Result", wrappers = [PageList::class])
open class ResultParser<T> : TypeParser<T> {
private lateinit var type: Type
//该构造方法是必须的
protected constructor() : super()
//如果依赖了RxJava,该构造方法也是必须的
constructor(type: Type) : super(type) {
this.type = type
}
@Throws(IOException::class)
override fun onParse(response: okhttp3.Response): T {
var str = response.body()?.string().str()
val result: T
if (response.isSuccessful) {
//更新token
val token = response.header("zzb-access-token").str()
if (!token.isNullOrBlank()) {
BaseToken.setToken(token)
}
/*if (type.typeName == String::class.java.name) {
Log.e("Hujx", "是String类型的!")
}*/
if (str.isBlank() && type.typeName != String::class.java.name) {
str = "{}"
}
result = JSONObject.parseObject(str, type) as T
} else {
val mBaseError = JSONObject.parseObject(str, BaseError::class.java)
ToastUtils.showLong(mBaseError.msg.str())
throw ParseException(mBaseError.code.str(), mBaseError.msg.str(), response)
}
return result
}
}
我用RxJava,是不是一定会调用下面这个构造方法?
constructor(type: Type) : super(type) { this.type = type }
我把type存起来,在下面使用,会不会有问题?
我看了下你刚才给发的代码,我这样好像是画蛇添足了,直接用types[0]就能拿到T的实际类型了
@Parser(name = "Result", wrappers = [PageList::class])
open class ResultParser<T> : TypeParser<T> {
protected constructor() : super()
constructor(type: Type) : super(type)
@Throws(IOException::class)
override fun onParse(response: okhttp3.Response): T {
var str = response.body()?.string().str()
val result: T
if (response.isSuccessful) {
//更新token
val token = response.header("zzb-access-token").str()
if (!token.isNullOrBlank()) {
BaseToken.setToken(token)
}
/*if (type.typeName == String::class.java.name) {
Log.e("Hujx", "是String类型的!")
}*/
if (str.isBlank() && types[0].typeName != String::class.java.name) {
str = "{}"
}
result = JSONObject.parseObject(str, types[0]) as T
} else {
val mBaseError = JSONObject.parseObject(str, BaseError::class.java)
ToastUtils.showLong(mBaseError.msg.str())
throw ParseException(mBaseError.code.str(), mBaseError.msg.str(), response)
}
return result
}
}
直接这样用就OK了,是吧?
可以,但你自己解析数据,会导致请求响应的日志不会输出
服务器数据返回规则: 请求成功:直接返回对象
{ "userId": "1", "name": "2", "age": 3 }
请求失败:返回{ "code":"E1001", "msg":"密码错误" }
这样一来就不能用之前的Result来解析:
我在ResultParser是这样写的:
使用:
这样解析出来报错: java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.zj.drone.bean.UserInfo