diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2021-05-03 19:07:01 +0000 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2021-05-14 20:39:01 +0000 |
| commit | a1076abac6cb43941f01e16dbe0156c6eacd0361 (patch) | |
| tree | 8af552c089136d8a6c18acdf0783bbfc620ba3ff /android | |
| parent | a486e2286ab6685e4e0e6d676587b629fa738404 (diff) | |
| download | mullvadvpn-a1076abac6cb43941f01e16dbe0156c6eacd0361.tar.xz mullvadvpn-a1076abac6cb43941f01e16dbe0156c6eacd0361.zip | |
Create `HandlerFlow` helper type
A handler message loop that can be used as a `Flow`.
Diffstat (limited to 'android')
| -rw-r--r-- | android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt new file mode 100644 index 0000000000..943c55eeff --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/HandlerFlow.kt @@ -0,0 +1,45 @@ +package net.mullvad.mullvadvpn.ipc + +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.util.Log +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.ClosedSendChannelException +import kotlinx.coroutines.channels.sendBlocking +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.consumeAsFlow +import kotlinx.coroutines.flow.onCompletion + +class HandlerFlow<T>( + looper: Looper, + private val extractor: (Message) -> T +) : Handler(looper), Flow<T> { + private val channel = Channel<T>(Channel.UNLIMITED) + private val flow = channel.consumeAsFlow().onCompletion { + removeCallbacksAndMessages(null) + } + + @InternalCoroutinesApi + override suspend fun collect(collector: FlowCollector<T>) = flow.collect(collector) + + override fun handleMessage(message: Message) { + val extractedData = extractor(message) + + try { + channel.sendBlocking(extractedData) + } catch (exception: Exception) { + when (exception) { + is ClosedSendChannelException, is CancellationException -> { + Log.w("mullvad", "Received a message after HandlerFlow was closed", exception) + removeCallbacksAndMessages(null) + } + else -> throw exception + } + } + } +} |
