【问题标题】:How to emit from a LiveData builder from a non-suspending callback function如何通过非挂起回调函数从 LiveData 构建器发出
【发布时间】:2020-03-12 17:07:15
【问题描述】:

我是 LiveData 和 Kotlin 协程的新手。我正在尝试使用 Chromium Cronet 库从我的存储库类发出请求以返回 LiveData 对象。为了返回 liveData,我使用了新的 LiveData 构建器 (coroutines with LiveData)。如何从成功的 Cronet 请求中发出结果?

class CustomRepository @Inject constructor(private val context: Context, private val gson: Gson) : Repository {
    private val coroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()

    override suspend fun getLiveData(): LiveData<List<MyItem>> = liveData(coroutineDispatcher) {
        val executor = Executors.newSingleThreadExecutor()
        val cronetEngineBuilder = CronetEngine.Builder(context)
        val cronetEngine = cronetEngineBuilder.build()
        val requestBuilder = cronetEngine.newUrlRequestBuilder(
            "http://www.exampleApi.com/example",
            CustomRequestCallback(gson),
            executor
        )
        val request: UrlRequest = requestBuilder.build()
        request.start()
    }

    class CustomRequestCallback(private val gson: Gson) : UrlRequest.Callback() {

        override fun onReadCompleted(request: UrlRequest?, info: UrlResponseInfo?, byteBuffer: ByteBuffer?) {
            byteBuffer?.flip()
            byteBuffer?.let {
                val byteArray = ByteArray(it.remaining())
                it.get(byteArray)
                String(byteArray, Charset.forName("UTF-8"))
            }.apply {
                val myItems = gson.fromJson(this, MyItem::class.java)
                // THIS IS WHAT I WANT TO EMIT
                // emit(myItems) doesn't work since I'm not in a suspending function
            }
            byteBuffer?.clear()
            request?.read(byteBuffer)
        }

        // other callbacks not shown
}

}

【问题讨论】:

    标签: kotlin android-livedata coroutine kotlin-coroutines cronet


    【解决方案1】:

    解决方案涉及将 UrlRequest.Callback 传统回调结构包装在 suspendCoroutine 构建器中。

    我还在讨论Cronet integration with LiveData and Kotlin CoroutinesMedium article 中记录了我的学习。

    override suspend fun getLiveData(): LiveData<List<MyItem>> = liveData(coroutineDispatcher) {
    
        lateinit var result: List<MyItem>
        suspendCoroutine<List<MyItem>> { continuation ->
    
            val requestBuilder = cronetEngine.newUrlRequestBuilder(
                "http://www.exampleApi.com/example",
                object : UrlRequest.Callback() {
    
                    // other callbacks not shown
    
                    override fun onReadCompleted(request: UrlRequest?, info: UrlResponseInfo?, byteBuffer: ByteBuffer?) {
                        byteBuffer?.flip()
                        byteBuffer?.let {
                            val byteArray = ByteArray(it.remaining())
                            it.get(byteArray)
                            String(byteArray, Charset.forName("UTF-8"))
                        }.apply {
                            val myItems = gson.fromJson(this, MyItem::class.java)
                            result = myItems
                            continuation.resume(result)
                        }
                        byteBuffer?.clear()
                        request?.read(byteBuffer)
                    },
                    executor
            )
            val request: UrlRequest = requestBuilder.build()
            request.start()
    
        }
        emit(result)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-21
      • 2020-04-17
      • 2020-04-13
      • 2022-12-03
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 2019-10-10
      相关资源
      最近更新 更多