day25 矮额是callback,把它变成flow好了 简单的callbackFlow

终於写道flow的最後一篇了

尽管我们在自己的开发上,能够高兴地写coroutine和suspend,但人生总是不那麽美好,我们会在各式sdk或套件里遇到callback,难道我们只能认命,乖乖地用callback完成那个功能

nono,coroutine的开发者做出了一个callbackfFlow的东西,可以将callback的值转成flow使用

范例

@ExperimentalCoroutinesApi
val callFlowResult = callbackFlow<Post> {
    repo.postCallback.enqueue(object :Callback<Post>{
        override fun onResponse(call: Call<Post>, response: Response<Post>) {
            trySend(response.body()!!)
        }
        override fun onFailure(call: Call<Post>, t: Throwable) {
            close(t)
        }
    })

    awaitClose{
        // clean up when Flow collection ends
    }
}

注意,网路上的每个范例,都会长得有点不同,以官方的其中一个来说

val locationsSource: Flow<Location> = callbackFlow<Location> {
    val callback = object : LocationCallback() {
        override fun onLocationResult(result: LocationResult?) {
            result ?: return
            try { offer(result.lastLocation) } catch(e: Exception) {}
        }
    }
    requestLocationUpdates(createLocationRequest(), callback, Looper.getMainLooper())
        .addOnFailureListener { e ->
            close(e) // in case of exception, close the Flow
        }
    // clean up when Flow collection ends
    awaitClose {
        removeLocationUpdates(callback)
    }
}

差很多吧,但你品,你细品,就是成功收到值时,offer(现在弃用,改用trysend),失败时close

正常结束时,awaitclose释放资源

运作

Internally, callbackFlow uses a channel, which is conceptually very similar to a blocking queue, and has a default capacity of 64 elements.

而callbackFlow底层是以channel去实作的,channel的特性就像是一个queue,如果没特别设置那预设的上限数是64。

lifecycleScope.launchWhenStarted suspends the execution of the coroutine. New locations are not processed, but the callbackFlow producer keeps sending locations nonetheless. Using the lifecycleScope.launch or launchIn APIs are even more dangerous as the view keeps consuming locations even if it’s in the background! Which could potentially make your app crash.

在ui层蒐集callackflow有说道launchWhenStart会在背景仍继续执行,我当时也是充满疑惑,因为flow不会channel也不会,所以又写了一些code来验证

最後得知,channel如果是用offer()的话,会有这种情况,但offer已经被弃用了,所以目前测试send()并不会在背景执行,而callbackFlow既然是以channel去实作,自然也会有相同的情况,但大家用channel记得去关掉喔

我也不敢把话讲太死,毕竟目前的官方资料还是以repeatOnLifecycle()为主,也提过launchWhenStart在一些intermediary的操作上还是会造成背景执行,如果有人看到更新的,欢迎在留言补充

连结

必看

essons-learnt-using-coroutines-flow

a-safer-way-to-collect-flows-from-android-ui


<<:  Day 25 : 经典气泡排序 Bubble Sort

>>:  Day 25:我可以写什麽内容到部落格?

[ASP.Net MVC] 如何套用 Bootstrap 网页设计样版 SB Admin 2 开发网站管理介面 (附范例)

想要快速开发一个 Bootstrap 网页设计样版的网站,可以利用网路上已经设计好的网页样版下载套用...

[Day30]蓝牙的学习笔记下台一鞠躬

终於完成三十天份量的文章了!!! 虽然蓝牙对我来说是一个已经认识一年多的主题 但是在撰写内容时还是觉...

[Day-23] R语言 - 分群应用(四) 建构新特徵 ( generate feature by clustering in R.Studio )

您的订阅是我制作影片的动力 订阅点这里~ 影片程序码 ## 应用四: 建构特徵 #### # 用GM...

[Day18] - 在 React 中引用现成的 Web Component

当我们拿到一个现有的 Web Component 时 , 如何在 React 专案中引用呢 ? 利用...

口罩脸孔资料集的训练(Training)

上一篇我们已经为资料集做好资料前处理、资料扩增与资料集版本建立, 接下来我们要开始执行trainin...