Kotlin + Retrofit + RxJava简单封装使用详解

时间:2022-08-30 19:21:36

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