为什么 Flow 可以在 Kotlin 中同时发出 Int 和 String 值?
Why can a Flow emit both Int and String value in Kotlin?
你知道 Array
和 List
只存储相同的数据结构。
我运行代码A得到结果A.
似乎 Flow
可以同时发出 Int
值和 String
值,为什么?
代码A
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
suspend fun performRequest(request: Int): Int {
delay(1000) // imitate long-running asynchronous work
return request
}
fun main() = runBlocking<Unit> {
(1..3).asFlow() // a flow of requests
.transform { request ->
emit("Making request $request")
if (request >1) {
emit(performRequest(request))
}
}
.collect { response -> println(response) }
}
结果A
Making request 1
Making request 2
2
Making request 3
3
这不是 Flow
的问题,而是 Java/Kotling 泛型和类型安全的问题。
此流 returns 的类型是 Comperable<*>
val flow: Flow<Comparable<*>> = (1..3).asFlow() // a flow of requests
.transform { request ->
emit("Making request $request")
if (request > 1) {
emit(performRequest(request))
}
如果您明确指定要使用的值 return Flow
您可以限制类型。
关于泛型可以参考here or check any document about generics in java/kotlin, type safety you can refer this question
此外,当您不确定您指定的类型是什么时,使用 alt + enter 和 Android Studio 查看可用的选项和 select 明确指定类型 .
不管这个请求的性质如何,您都可以通过让您的流程发出一些代数数据类型的实例来获得您想要的功能,这些代数数据类型基本上是您的组成部分的“总和”(来自 type-theoretic POV)类型:
sealed interface Record
data class IntData(val get: Int) : Record
data class Metadata(val get: String) : Record
// somewhere later (flow is of type Flow<Record>)
fun main() = runBlocking<Unit> {
(1..3).asFlow() // a flow of requests
.transform { request ->
emit(Metadata("Making request $request"))
if (request > 1) {
emit(IntData(performRequest(request)))
}
// probably want to handle the `else` case too
}
.collect { response -> println(response) }
}
这将是一个很好的解决方案,因为它是可扩展的(即,如果需要,您可以稍后添加其他案例)。
不过在您的具体情况下,由于您只想调试流程,您可能不想实际发出“元数据”而只是直接测试您的代码。
你知道 Array
和 List
只存储相同的数据结构。
我运行代码A得到结果A.
似乎 Flow
可以同时发出 Int
值和 String
值,为什么?
代码A
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
suspend fun performRequest(request: Int): Int {
delay(1000) // imitate long-running asynchronous work
return request
}
fun main() = runBlocking<Unit> {
(1..3).asFlow() // a flow of requests
.transform { request ->
emit("Making request $request")
if (request >1) {
emit(performRequest(request))
}
}
.collect { response -> println(response) }
}
结果A
Making request 1
Making request 2
2
Making request 3
3
这不是 Flow
的问题,而是 Java/Kotling 泛型和类型安全的问题。
此流 returns 的类型是 Comperable<*>
val flow: Flow<Comparable<*>> = (1..3).asFlow() // a flow of requests
.transform { request ->
emit("Making request $request")
if (request > 1) {
emit(performRequest(request))
}
如果您明确指定要使用的值 return Flow
您可以限制类型。
关于泛型可以参考here or check any document about generics in java/kotlin, type safety you can refer this question
此外,当您不确定您指定的类型是什么时,使用 alt + enter 和 Android Studio 查看可用的选项和 select 明确指定类型 .
不管这个请求的性质如何,您都可以通过让您的流程发出一些代数数据类型的实例来获得您想要的功能,这些代数数据类型基本上是您的组成部分的“总和”(来自 type-theoretic POV)类型:
sealed interface Record
data class IntData(val get: Int) : Record
data class Metadata(val get: String) : Record
// somewhere later (flow is of type Flow<Record>)
fun main() = runBlocking<Unit> {
(1..3).asFlow() // a flow of requests
.transform { request ->
emit(Metadata("Making request $request"))
if (request > 1) {
emit(IntData(performRequest(request)))
}
// probably want to handle the `else` case too
}
.collect { response -> println(response) }
}
这将是一个很好的解决方案,因为它是可扩展的(即,如果需要,您可以稍后添加其他案例)。
不过在您的具体情况下,由于您只想调试流程,您可能不想实际发出“元数据”而只是直接测试您的代码。