![](/img/trans.png)
[英]How to make viewModelScope wait for a suspend function in unit test
[英]How can I use suspend function or viewModelScope/lifecycleScope in WebSocketListener?
我用 WebSocketListener 实现了 WebSocket。 我想使用协程通道。 但是现在我需要在 Coroutine Scope 中调用它。 在这里,我没有 viewModelScope 也没有生命周期范围。 所以,我使用了 GlobalScope。 而且我认为这可能会导致 memory 泄漏和不正确的行为。
@OptIn(DelicateCoroutinesApi::class)
class CustomWebSocketListener : WebSocketListener() {
val socketEventChannel: Channel<SocketUpdate> = Channel(10)
override fun onOpen(webSocket: WebSocket, response: Response) {
// no-op
}
override fun onMessage(webSocket: WebSocket, text: String) {
GlobalScope.launch {
socketEventChannel.sendOrNothing(SocketUpdate(text = text))
}
}
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
GlobalScope.launch {
socketEventChannel.sendOrNothing(SocketUpdate(exception = SocketAbortedException()))
}
webSocket.close(1000, null)
socketEventChannel.close()
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
GlobalScope.launch {
socketEventChannel.sendOrNothing(SocketUpdate(exception = t))
}
}
private suspend fun <E> Channel<E>.sendOrNothing(e: E) {
try {
this.send(e)
} catch (e: ClosedSendChannelException) {
e.printStackTrace()
}
}
}
我像这样使用 CustomWebSocketListener:
suspend fun startOrReloadSocket(url: String): Channel<SocketUpdate> {
if(isConnected()) {
if(url == webSocketUrl) {
return webSocketListener!!.socketEventChannel
} else {
stopSocket()
}
}
return with(CustomWebSocketListener()) {
startOrReloadSocket(url,this)
this@with.socketEventChannel
}
}
我做这个是为了使用监听器。 如何将侦听器包含在同一个协程 scope 中以便我可以使用 viewModelScope?(在 viewModelScope 中调用了挂起函数(startOrReloadSocket))
您可以使用suspendCoroutine块将您的回调转换为挂起函数。 这是一个有用的链接
如何在 WebSocketListener 中使用暂停 function 或 viewModelScope/lifecycleScope?
eventChannel
不是rendezvous
通道。 因此,您只需使用trySend
进行事件生成并在生命周期中使用。
生产
/**
* If you want handle result of event produce :
*
* ChannelResult result = socketEventChannel.trySend(~)
* if(result.isFailure) {
* handle error
* }
**/
override fun onMessage(webSocket: WebSocket, text: String) {
socketEventChannel.trySend(SocketUpdate(text = text))
}
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
socketEventChannel.trySend(SocketUpdate(exception = SocketAbortedException()))
webSocket.close(1000, null)
socketEventChannel.close()
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
socketEventChannel.trySend(SocketUpdate(exception = t))
}
消耗
viewModelScope or lifecycleScope.launch {
listener.socketEventChannel.consumeEach {
// TODO : handle socket event
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.