协程+Retrofit 封装一个网络请求框架

5,346 阅读3分钟

前言

好久没有写博客了,笔者最近也是比较忙。刚刚换了工作,刚刚入职一个月,唉,周末还要回家去,一直没时间写博客,今天终于还是抽时间将这个博客给发出来了。

关于网络请求。大家了解的 无非就是 okhttp, retrofit2 这些大厂出来的框架。用起来顺手,很多人包括笔者都会在自己加上一层封装。主要是为了自己项目中使用方便。

kotlin 已经出来很久了。相信大家都用的比较熟悉。笔者今天带来的就是 协程+ Retrofit 进行封装的网络请求框架。

基础使用

现在人都急性子。先给大家看看使用是一个get 请求的样子。首先是配置。笔者这里使用DSL风格去配置基础的信息等。也是方便哈。

private val moya by lazy {
    moya(this) {
        url = "https://www.wanandroid.com"
        retry = true
        time = {
            connect = 10L
            write = 10L
            read = 10L
        }
        cache = {
            type = CacheType.NONE
            path = ""
            size = 10
            noNetworkTimeOut = 10
            networkTimeOut = 10
        }
        head = {
            put("hello", "world")
        }
        log = {
            level = LoggerLevel.BASIC
            interceptors = setOf(object : OnLogInterceptor {
                override fun onLogInterceptorInfo(message: String) {

                }
            })
        }

        adapter = {}
        converter = {}
        cookie = {}
    }
  }

然后就是使用。简单的get 请求。

viewModel.viewModelScope.launch {
    moya.create()
        .parameter("username", "moya")
        .parameter("password", "123456")
        .parameter("repassword", "123456")
        .doPost<RegisterData>("user/register")
        .doComplete { hideLoadDialog() }
        .doFailed { showRequestDialog(it.message ?: " is empty ") }
        .doSuccess { showRequestDialog(it.toString()) }
}

设计思路

其实还是想将自己这次封装的心得分享给大家。先给大家看一下项目的架构

image.png

  • 使用了插件作为依赖管理 这么干主要还是为了方便。这种方式在我忘记在哪看到的了。不过觉得其实还行。比BuildSrc方便一点。

  • 项目分成了基础模块和协程模块 这里就为了拓展。想着以后还要将RxJava那套加进来。所以很多核心的功能都放在了moya中。

  • 协程的拓展功能都使用Kotlin 的拓展函数去完成

主要还是一个字。香!

关于配置

这个就简单了。主要就使用了构造者模式去创建一个对象。笔者遇到的坑就是关于 DSL 部分。如果能够实现我在上面实现的那种方式。以网络超时为例。

// 配置网络超时时间等
var Moya.Builder.time: NetWorkTimeOut.() -> Unit by LambdaDelegate<NetWorkTimeOut, Moya.Builder>(
    NetWorkTimeOut()
) { netWorkTime, builder ->
    builder.connectTimeout(time = netWorkTime.connect)
    builder.readTimeout(time = netWorkTime.read)
    builder.writeTimeout(time = netWorkTime.write)
}

其核心代码就这么几行。这么看有点意思吧,当然用到了拓展函数还有委托。 就能够实现 time{}的效果,为了控制作用域笔者还是用了DslMarker去控制他。

动态修改url

其实这个需求很少遇到,不过遇到了,之前看到有人创建了多个 retrofit对象去控制,不好啊。其实可以是用拦截器控制的。笔者这里也直接写好了。只需要在请求中加入下面的代码就能够动态替换url

baseUrl("new host url")

原理嘛,就是拦截器,放上核心代码,详细的可以去看源码哈。

override fun intercept(chain: Interceptor.Chain): Response {

    var request = chain.request()
    val headers = request.headers

    if (headers.size > 0) {
        val url = headers[DynamicHeard.DYNAMIC_URL]
        if (url != null) {
            val httpUrl = request.url
            val newBuilder = httpUrl.newBuilder()
            checkBaseUrl(url, newBuilder)
            setNewHost(url, newBuilder)
            request = request.newBuilder()
                .removeHeader(DynamicHeard.DYNAMIC_URL)
                .url(newBuilder.build())
                .build()
            return chain.proceed(request)
        }
    }
    return chain.proceed(request)
}

动态修改请求超时

其实也是一个比较小众的需求。依然可以通过拦截器去触发。笔者这里也写好了 connectTimeOut 在请求中加入下面代码就能配置请求超时时间啦。方便哈

.connectTimeOut(1)

最后

写这个小框架,笔者也学习了很多,对kotiln 的理解也更佳深了,项目中放在了 moya 有兴趣的读者可以自行学习哈。

最后的最后。新工作有点小累,也发现了自己的很多不足。期待更上一成楼。