I implemented WebSocket with WebSocketListener. And I want to use coroutine channel. But now I need to call it in Coroutine Scope. Here, I don't have viewModelScope nor lifecycleScope. So, I used GlobalScope. And I think this might cause memory leak and incorrect behaviour.
@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()
}
}
}
I use CustomWebSocketListener like this:
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
}
}
I made this for using the listener. How can I include the listener in the same coroutine scope so that I can use viewModelScope?(the suspend function(startOrReloadSocket) is called in the viewModelScope)