Kotlin+Rxjava+Retrofit+okHttp网络请求封装

[toc]

依赖

ext.kotlin_version = "1.5.0"
ext.retrofit_version = "2.9.0"
ext.ok_http_version = "3.4.1"
ext.rx_kotlin_version = '3.0.1'
ext.rx_android_version ='3.0.0'

implementation "com.squareup.okhttp3:okhttp:$ok_http_version"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.okhttp3:logging-interceptor:$ok_http_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "com.squareup.retrofit2:adapter-rxjava3:$retrofit_version"

implementation "io.reactivex.rxjava3:rxkotlin:$rx_kotlin_version"
implementation "io.reactivex.rxjava3:rxandroid:${rx_android_version}"

封装步骤

1.配置Retrofit,okHttpClient

/**
 * create by Admin in 2021/6/8
 *
 * @Description : retrofit封装
 **/
class RetrofitFactory {
    private lateinit var retrofit:Retrofit
    companion object{
        //单例
        val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            RetrofitFactory()
        }
    }

    /**
     * 组装retrofit对象
     */
    init {
        retrofit = Retrofit.Builder()
            .baseUrl(NetContants.BASE_URL)
            .client(getClient())
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
            .build()
    }

    /**
     * 组装client
     */
    private fun getClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .writeTimeout(10,TimeUnit.SECONDS)
            .readTimeout(10,TimeUnit.SECONDS)
            .connectTimeout(10,TimeUnit.SECONDS)
            .addInterceptor(getLogInterceptor())
            .build()

    }

    /**
     * log 拦截器
     */
    private fun getLogInterceptor(): Interceptor {
        val logInterceptor = HttpLoggingInterceptor()
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
        return logInterceptor
    }

    /**
     * service
     */
    fun <T> create(service:Class<T>):T{
        return retrofit.create(service)
    }

}

2.创建请求接口apiService

/**
 * create by Admin in 2021/6/8
 *
 * @Description : retrofit抽象接口
 **/
interface UserApiService {
    //登录接口
    @FormUrlEncoded
    @POST("user/login")
    fun login(@Field("userName") userName: String,
              @Field("password") password: String): Observable<BaseRep<LoginBean>>
}

2.1返回数据封装

/**
 * create by Admin in 2021/6/8
 *
 * @Description : 接口返回格式
 **/
data class BaseRep<T>(val data:T,val errorCode:Int,val errorMsg:String)

3.请求接口

/**
 * create by Admin in 2021/6/8
 *
 * @Description : 用户模块接口请求
 **/
class UserServiceImpl : UserService {
    val userResposity by lazy { UserRepository() }
    override fun login(userName: String, pwd: String) {
        println("loading开始")
        userResposity.login(userName, pwd).covert()
            .execute(object : BaseObserver<LoginBean>() {
                override fun onNext(t: LoginBean?) {
                    super.onNext(t)
                    println("登录成功")
                }
            })
    }
}

3.1返回数据转换

/*
*  返回数据转换
*/
fun <T> Observable<BaseRep<T>>.covert():Observable<T>{
    return this.flatMap(object :Function<BaseRep<T>,Observable<T>>{
        override fun apply(t: BaseRep<T>): Observable<T> {
            if(t.errorCode != 0){
                return Observable.error(BaseException(t.errorCode,t.errorMsg))
            }else{
                return Observable.just(t.data)
            }
        }
    })
}

3.2rx封装

/*
*  Observable扩展
*/
fun <T> Observable<T>.execute(observer:BaseObserver<T>){
    this.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(observer)
}

3.3错误处理

open class BaseObserver<T> : Observer<T> {
    override fun onSubscribe(d: Disposable?) {

    }

    override fun onNext(t: T?) {
    }

    override fun onError(e: Throwable?) {
        if(e is BaseException){
            println(e.errorMsg)
        }else{
            val errorMsg = NetExceptionUtils.exceptionHandler(e!!)
            println(errorMsg)
        }
        println("loading结束")
    }

    override fun onComplete() {
        println("loading结束")
    }
}
/**
 * create by Admin in 2021/6/9
 *
 * @Description : 异常信息封装
 **/
object NetExceptionUtils {

    fun exceptionHandler(e: Throwable): String {
        var errorMsg = "未知错误"
        when (e) {
            is UnknownHostException -> {
                errorMsg = "网络不可用"
            }
            is SocketTimeoutException -> {
                errorMsg = "请求网络超时"
            }
            is HttpException -> {
                val httpException = e as HttpException
                errorMsg = covertStatusCode(httpException)
            }
            is ParseException,
            is JSONException -> {
                errorMsg = "数据解析错误"
            }
        }
        return errorMsg
    }

    private fun covertStatusCode(httpException: HttpException): String {
        var msg = ""
        when (httpException.code()) {
            in 500 until 600 -> {
                msg = "服务器处理请求错误"
            }
            in 400 until 500 -> {
                msg = "服务器无法处理请求"
            }
            in 300 until 400 -> {
                msg = "请求被重定向到其他界面"
            }
            else -> {
                msg = httpException.message()
            }
        }
        return msg
    }
}

执行结果

D/OkHttp: {"data":null,"errorCode":-1,"errorMsg":"账号密码不匹配!"}
    <-- END HTTP (66-byte body)
I/System.out: 账号密码不匹配!
    loading结束

参考资料

api地址
源码地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容