本文介绍了kotlin + retrofit + rxjava简单封装使用详解,分享给大家,具体如下:
实例化retrofit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
object retrofitutil {
val connect_time_out = 30 //连接超时时长x秒
val read_time_out = 30 //读数据超时时长x秒
val write_time_out = 30 //写数据接超时时长x秒
val retrofit: retrofit by lazy {
log.d( "retrofitutil" , "retrofit init lazy" )
retrofit.builder()
.baseurl( "http://gank.io/api/" ) //本文以github api为例
.addconverterfactory(gsonconverterfactory.create())
.addcalladapterfactory(rxjava2calladapterfactory.create())
.client(getokhttpclient())
.build()
}
private fun getokhttpclient(): okhttpclient {
val builder = okhttpclient.builder()
builder.connecttimeout(connect_time_out.tolong(), timeunit.seconds)
.writetimeout(write_time_out.tolong(), timeunit.seconds)
.readtimeout(read_time_out.tolong(), timeunit.seconds)
if (buildconfig.debug) {
builder.addinterceptor(httplogginginterceptor().setlevel(httplogginginterceptor.level.body))
} else {
builder.addinterceptor(httplogginginterceptor().setlevel(httplogginginterceptor.level.none))
}
// 设置请求头
builder.addinterceptor { chain ->
val time = (system.currenttimemillis() / 1000 ).tostring() + ""
val requestbuilder = chain.request().newbuilder()
requestbuilder.addheader( "time" , time)
chain.proceed(requestbuilder.build())
}
return builder.build()
}
}
|
返回数据封装
1
2
3
4
|
class response<t> {
var error: boolean = false
var results: t? = null
}
|
demo中用了gank.io的开发api,之前一般项目的返回格式是code + message + t的格式。
api接口错误/异常统一处理类
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class apiexception : exception {
var code: int = 0 //错误码
var msg: string? = null //错误信息
constructor(throwable: throwable, code: int ) : super (throwable) {
this .code = code
}
constructor(code: int , msg: string) {
this .code = code
this .msg = msg
}
}
|
定义exceptionfunction处理onerrorresumenext:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
class exceptionfunction<t> : function<throwable, observable<t>> {
override fun apply( @nonnull throwable: throwable): observable<t> {
log.e( "exceptionfunction" , throwable.message)
return observable.error(exceptionengine().handleexception(throwable))
}
}
/**
* 错误/异常处理工具
*/
class exceptionengine {
val un_known_error = 1000 //未知错误
val analytic_server_data_error = 1001 //解析(服务器)数据错误
val connect_error = 1002 //网络连接错误
val time_out_error = 1003 //网络连接超时
fun handleexception(e: throwable): apiexception {
val ex: apiexception
if (e is apiexception) { //服务器返回的错误
return e
} else if (e is httpexception) { //http错误
ex = apiexception(e, e.code())
ex.msg = "网络错误:" + ex.code
return ex
} else if (e is jsonparseexception
|| e is jsonexception
|| e is parseexception || e is malformedjsonexception) { //解析数据错误
ex = apiexception(e, analytic_server_data_error)
ex.msg = "解析错误"
return ex
} else if (e is connectexception) { //连接网络错误
ex = apiexception(e, connect_error)
ex.msg = "连接失败"
return ex
} else if (e is sockettimeoutexception) { //网络超时
ex = apiexception(e, time_out_error)
ex.msg = "网络超时"
return ex
} else { //未知错误
ex = apiexception(e, un_known_error)
ex.msg = e.message
return ex
}
}
}
|
封装请求处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
object rx {
/**
* rxlifecycle绑定生命周期
*/
fun <t, e> get(observable: observable<response<t>>, lifecycleprovider: lifecycleprovider<e>): observable<t> {
// 请求绑定生命周期,防止内存泄漏,同时返回回调之后页面已销毁造成的空指针错误
if (lifecycleprovider is rxappcompatactivity) {
val rxappcompatactivity = lifecycleprovider as rxappcompatactivity
observable.compose(rxappcompatactivity.binduntilevent(activityevent.destroy))
} else if (lifecycleprovider is rxfragment) {
val rxfragment = lifecycleprovider as rxfragment
observable.compose(rxfragment.binduntilevent(fragmentevent.destroy))
}
return observable
.compose(handleresult())
.onerrorresumenext(exceptionfunction())
}
/**
* 部分后台请求
*/
fun <t> get(observable: observable<response<t>>): observable<t> {
return observable
.compose(handleresult())
.onerrorresumenext(exceptionfunction())
}
private class handleresult<t> : observabletransformer<response<t>, t> {
override fun apply(upstream: observable<response<t>>): observablesource<t> {
return upstream.flatmap { response -> createresult(response) }
.subscribeon(schedulers.io())
.unsubscribeon(schedulers.io())
.observeon(androidschedulers.mainthread())
}
}
private fun <t> createresult(response: response<t>): observable<t> {
return observable.create({ subscriber ->
if (response.error)
throw apiexception(- 1 , "服务器异常" ) // 一般来说,自己的服务器异常会返回相应的code和message
else
response.results?.let {
subscriber.onnext(response.results!!)
} ?: subscriber.oncomplete()
})
}
}
|
定义httpobserver统一处理返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
abstract class httpobserver<t> : observer<t> {
/**
* 标记是否为特殊情况
*/
private var resultnull: boolean = true
override fun oncomplete() {
// 特殊情况:当请求成功,但t == null时会跳过onnext,仍需当成功处理
if (resultnull)
onsuccess( null )
}
override fun onsubscribe(d: disposable) {
// 可在此处加上dialog
}
override fun onerror(e: throwable) {
if (e is apiexception) {
onerror(e.code, e.msg)
} else {
onerror( 0 , e.message)
}
}
override fun onnext(t: t) {
resultnull = false
onsuccess(t)
}
abstract fun onsuccess(t: t?)
/**
* 统一处理失败,比如登录失效等
*
* @param code
* @param msg
*/
open fun onerror(code: int , msg: string?) {
}
}
|
api
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
class result {
var _id: string? = null
var createdat: string? = null
var desc: string? = null
var publishedat: string? = null
var source: string? = null
var type: string? = null
var url: string = ""
var isused: boolean = false
var who: string? = null
var images: list<string>? = null
/**
* 妹子小图
*/
fun meizismallurl(): string {
val meizi = url
return meizi.replace( "large" , "small" )
}
}
interface apiservice {
@get ( "data/{type}/10/{page}" )
fun getgank( @path ( "type" ) type: string, @path ( "page" ) page: int ): observable<response<list<result>>>
}
object api {
val apiservice: apiservice by lazy {
log.d( "api" , "apiservice create lazy" )
retrofitutil.retrofit.create(apiservice:: class .java)
}
}
|
使用
1
2
3
4
5
6
7
8
9
10
11
12
|
override fun loaddata() {
rx.get(api.apiservice.getgank(gettype(), mintpage), this ).subscribe(object : httpobserver<list<result>>() {
override fun onsuccess(t: list<result>?) {
//getdatasuccess(t)
}
override fun onerror(code: int , msg: string?) {
super .onerror(code, msg)
//getdatafailed()
}
})
}
|
使用了rxlifecycle绑定生命周期来处理可能发生的内存泄漏问题,fragment跟activity需要继承rx相应的基类。
练手项目
meizikt gank.io android客户端,使用kotlin + retrofit2 + rxjava
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.jianshu.com/p/e5f2bb8738db