在 Android 中使用 Ktor 请求

作者: 何晓杰Dev | 来源:发表于2019-05-14 15:39 被阅读54次

    Ktor 除了可以完成服务端的开发,同样也可以用于客户端,在 Android 可以简单的用 Ktor 来取代掉以往的各种请求响应,天生协程的 Ktor 可以方便的完成很多事情。

    那么下面来写一下代码吧,首先引用相应的库:

    implementation "io.ktor:ktor-client-android:1.1.5"
    

    然了个后,使用 Android 端的 HttpClient 就可以了:

    var ret: String? = null
    val client = HttpClient(Android) {
        engine {
            connectTimeout = 100_000
            socketTimeout = 100_000
        }
    }
    try {
        ret = client.get<String>(url) { }
    } catch (e: Exception) {
    } finally {
        client.close()
    }
    return ret
    

    这段代码用在 Ktor 后端程序时没有任何的问题,然而对于 Android 来说,没有天生协程是一个很大的问题,因为 client.get() 是一个协程方法,也就是调用者必须是被 suspend 关键字标记的。

    如下所示:

    suspend fun req(url: String): String { ... }
    

    这个方法在 Android 的上下文内是不可能被直接调用的,没有任何上下文可以接受 suspend 方法。这个时候我们需要自己创建一个协程。

    按通常的线程写法,我们也可以提炼出协程的写法,线程的 kotlin 写法如下:

    thread {
        runOnMainThread {
            ... ...
        }
    }
    

    所以可以把协程也弄成类似的形式。


    那么下面来解决协程的问题,首先还是得引用协程的库:

    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1"
    

    这里需要注意,千万不要用 1.1.0 以下版本的协程库,那个版本的主线程调度有 bug,会引起一个 crash。

    然后写两个方法:

    fun coroutine(block: suspend () -> Unit) { CoroutineScope(Dispatchers.IO).launch { block() } }
    fun coroutineMain(block: suspend () -> Unit) { CoroutineScope(Dispatchers.Main).launch { block() } }
    

    很明显的,这就是协程的壳子了,把上面的代码写进去就好:

    fun req(url: String, callback:(String?) -> Unit) = coroutine {
        var ret: String? = null
        val client = HttpClient(Android) {
            engine {
                connectTimeout = 100_000
                socketTimeout = 100_000
            }
        }
        try {
            ret = client.get<String>(url) { }
        } catch (e: Exception) {
        } finally {
            client.close()
        }
        coroutineMain { callback(ret) }
    }
    

    到此,就可以在 Android 里愉快的使用 Ktor 了。

    最后,如果因为包含了 ktor-clientkotlinx-coroutines 带来了编译问题,可以在 Gradle 内加入以下代码来解决:

    packagingOptions {
        exclude 'META-INF/kotlinx-io.kotlin_module'
        exclude 'META-INF/atomicfu.kotlin_module'
        exclude 'META-INF/kotlinx-coroutines-io.kotlin_module'
        exclude 'META-INF/kotlinx-coroutines-core.kotlin_module'
    }
    

    相关文章

      网友评论

        本文标题:在 Android 中使用 Ktor 请求

        本文链接:https://www.haomeiwen.com/subject/rnisaqtx.html