在这之前的26天,我们所用的都是我要做什麽事,就是做什麽事,不会有条件的选取,但作为android的开发者,一定听过google爸爸说过single trust of source,在架构的最佳化那篇里面,他以最近是否活跃为判断连结
那我这边再多举一个例子,假如你的应用可以离线存取,同时也有客制排序的功能,用户对这项功能的调整频率较低,你可能会选择远端一份排序逻辑资料,本地一份排序逻辑资料
如果是用户自己设置,你可以在设置确认後先发到远端,在更新本地,如果是slope one的算法你可以考虑用workManager去定时fetch等等,在多种情境下我们会做不同的考量,而我这里在系列文里最後介绍一个coroutine的工具,select
中文好像叫多路复用,其实他就是会先拿到最早available的值
viewModelScope.launch {
val orderRule = select<OrderResponse<OrderRule>> {
async { localOrder() }.onAwait{ OrderResponse(it, isLocal = true)}
async { remoteOrder() }.onAwait{ OrderResponse(it, isLocal = false) }
}
}
而select也可以接收多个channel,通常我们一个channel是可以由多个priducer和多consumer对吧
但如果需求是要同时接收不同的channel呢? 最适合的工具就是select了
suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
select<Unit> { // <Unit> 意味着该 select 表达式不返回任何结果
fizz.onReceive { value -> // 这是第一个 select 子句
println("fizz -> '$value'")
}
buzz.onReceive { value -> // 这是第二个 select 子句
println("buzz -> '$value'")
}
}
}
val fizz = fizz()//启动一个corotine,每0.3秒丢值
val buzz = buzz()//启动一个corotine,每0.5秒丢值
repeat(7) {
selectFizzBuzz(fizz, buzz)
}//蒐集7个
coroutineContext.cancelChildren() //取消两个coroutine
文档给的范例非常简单,我也就不多加叙述了
那如果蒐集到已经close的channel要怎麽半?
onReceive会throw Exception,但我们可以用onReceiveOrNull,如果channel close他会回传null,而我们可以再对此作处理
b.onReceiveOrNull { value ->
if (value == null)
"Channel 'b' is closed"
else
"b -> '$value'"
}
而channel的接收和发送都会suspend,select也能对发送做出处理
fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
for (num in 1..10) { // 生产从 1 到 10 的 10 个数值
delay(100) // 延迟 100 毫秒
select<Unit> {
onSend(num) {} // 发送到主通道
side.onSend(num) {} // 或者发送到 side 通道
}
}
}
大概酱,因为再channel的consume那边,可能会执行其他动作,这时select救苦以尽快将值发给已经可以此用的channel里面
其实select是个比较少用到的功能,但听我讲讲你也不吃亏,先有个概念,未来遇到问题时也能很快联想到这个解法,今天就这样,掰掰
开始部属 点击 登入後会看到这个画面 点击左上方的加号 进行第一次的线上coding 在main上输...
golang 服务 常用於 http server/ http client 来看看一张厉害的图儿 ...
今天迈入第7天,根据计画,前几天我们介绍了一些登录档的基础知识和前置作业,假设读者跟笔者一样略懂略懂...
铁人赛进入尾声了,和大家分享个好消息,这支 WordPress 付款外挂已经写好送审到 WordPr...
今天大概会聊到的范围 Theme 透过 Android Studio 内建的精灵建立一个新的 Co...