欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-20 20:53:28
本文介绍了kotlin + retrofit + rxjava简单封装使用详解,分享给大家,具体如下: 实例化retrofit object retrofi...

本文介绍了kotlin + retrofit + rxjava简单封装使用详解,分享给大家,具体如下:

实例化retrofit

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()
  }
}

返回数据封装

class response<t> {
  var error: boolean = false
  var results: t? = null
}

demo中用了gank.io的开发api,之前一般项目的返回格式是code + message + t的格式。

api接口错误/异常统一处理类

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:

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
    }
  }
}

封装请求处理

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统一处理返回

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

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)
  }
}

使用

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: