本文介紹了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