Improve network state observer
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package org.koitharu.kotatsu.core.os
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager.NetworkCallback
|
||||
import android.net.Network
|
||||
import android.net.NetworkRequest
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.first
|
||||
import org.koitharu.kotatsu.utils.MediatorStateFlow
|
||||
import org.koitharu.kotatsu.utils.ext.connectivityManager
|
||||
import org.koitharu.kotatsu.utils.ext.isNetworkAvailable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class NetworkState @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
) : MediatorStateFlow<Boolean>() {
|
||||
|
||||
private val connectivityManager = context.connectivityManager
|
||||
private val callback = NetworkCallbackImpl()
|
||||
|
||||
override val initialValue: Boolean
|
||||
get() = connectivityManager.isNetworkAvailable
|
||||
|
||||
override fun onActive() {
|
||||
val request = NetworkRequest.Builder().build()
|
||||
connectivityManager.registerNetworkCallback(request, callback)
|
||||
}
|
||||
|
||||
override fun onInactive() {
|
||||
connectivityManager.unregisterNetworkCallback(callback)
|
||||
}
|
||||
|
||||
suspend fun awaitForConnection() {
|
||||
if (value) {
|
||||
return
|
||||
}
|
||||
first { it }
|
||||
}
|
||||
|
||||
private inner class NetworkCallbackImpl : NetworkCallback() {
|
||||
|
||||
override fun onAvailable(network: Network) = update()
|
||||
|
||||
override fun onLost(network: Network) = update()
|
||||
|
||||
override fun onUnavailable() = update()
|
||||
|
||||
private fun update() {
|
||||
publishValue(connectivityManager.isNetworkAvailable)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package org.koitharu.kotatsu.core.os
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager.NetworkCallback
|
||||
import android.net.Network
|
||||
import android.net.NetworkRequest
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.channels.ProducerScope
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.onSuccess
|
||||
import kotlinx.coroutines.channels.trySendBlocking
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import org.koitharu.kotatsu.utils.ext.connectivityManager
|
||||
import org.koitharu.kotatsu.utils.ext.isNetworkAvailable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class NetworkStateObserver @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
) : StateFlow<Boolean> {
|
||||
|
||||
private val connectivityManager = context.connectivityManager
|
||||
|
||||
override val replayCache: List<Boolean>
|
||||
get() = listOf(value)
|
||||
|
||||
override val value: Boolean
|
||||
get() = connectivityManager.isNetworkAvailable
|
||||
|
||||
override suspend fun collect(collector: FlowCollector<Boolean>): Nothing {
|
||||
collector.emit(value)
|
||||
while (true) {
|
||||
observeImpl().collect(collector)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun awaitForConnection(): Unit {
|
||||
if (value) {
|
||||
return
|
||||
}
|
||||
first { it }
|
||||
}
|
||||
|
||||
private fun observeImpl() = callbackFlow<Boolean> {
|
||||
val request = NetworkRequest.Builder().build()
|
||||
val callback = FlowNetworkCallback(this)
|
||||
connectivityManager.registerNetworkCallback(request, callback)
|
||||
awaitClose {
|
||||
connectivityManager.unregisterNetworkCallback(callback)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class FlowNetworkCallback(
|
||||
private val producerScope: ProducerScope<Boolean>,
|
||||
) : NetworkCallback() {
|
||||
|
||||
private var prevValue = value
|
||||
|
||||
override fun onAvailable(network: Network) = update()
|
||||
|
||||
override fun onLost(network: Network) = update()
|
||||
|
||||
override fun onUnavailable() = update()
|
||||
|
||||
private fun update() {
|
||||
val newValue = connectivityManager.isNetworkAvailable
|
||||
if (newValue != prevValue) {
|
||||
producerScope.trySendBlocking(newValue).onSuccess {
|
||||
prevValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import androidx.annotation.CallSuper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.LayoutPageInfoBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -14,12 +14,12 @@ abstract class BasePageHolder<B : ViewBinding>(
|
||||
protected val binding: B,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkStateObserver: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) : RecyclerView.ViewHolder(binding.root), PageHolderDelegate.Callback {
|
||||
|
||||
@Suppress("LeakingThis")
|
||||
protected val delegate = PageHolderDelegate(loader, settings, this, networkStateObserver, exceptionResolver)
|
||||
protected val delegate = PageHolderDelegate(loader, settings, this, networkState, exceptionResolver)
|
||||
protected val bindingInfo = LayoutPageInfoBinding.bind(binding.root)
|
||||
|
||||
val context: Context
|
||||
|
||||
@@ -5,7 +5,7 @@ import androidx.recyclerview.widget.AsyncListDiffer
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
import org.koitharu.kotatsu.utils.ext.resetTransformations
|
||||
@@ -16,7 +16,7 @@ import kotlin.coroutines.suspendCoroutine
|
||||
abstract class BaseReaderAdapter<H : BasePageHolder<*>>(
|
||||
private val loader: PageLoader,
|
||||
private val readerSettings: ReaderSettings,
|
||||
private val networkState: NetworkStateObserver,
|
||||
private val networkState: NetworkState,
|
||||
private val exceptionResolver: ExceptionResolver,
|
||||
) : RecyclerView.Adapter<H>() {
|
||||
|
||||
@@ -70,7 +70,7 @@ abstract class BaseReaderAdapter<H : BasePageHolder<*>>(
|
||||
parent: ViewGroup,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
): H
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -28,7 +28,7 @@ class PageHolderDelegate(
|
||||
private val loader: PageLoader,
|
||||
private val readerSettings: ReaderSettings,
|
||||
private val callback: Callback,
|
||||
private val networkState: NetworkStateObserver,
|
||||
private val networkState: NetworkState,
|
||||
private val exceptionResolver: ExceptionResolver,
|
||||
) : DefaultOnImageEventListener, Observer<ReaderSettings> {
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import android.widget.FrameLayout
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.ItemPageBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -16,7 +16,7 @@ class ReversedPageHolder(
|
||||
binding: ItemPageBinding,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) : PageHolder(binding, loader, settings, networkState, exceptionResolver) {
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.reader.ui.pager.reversed
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.ItemPageBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -12,7 +12,7 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
||||
class ReversedPagesAdapter(
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) : BaseReaderAdapter<ReversedPageHolder>(loader, settings, networkState, exceptionResolver) {
|
||||
|
||||
@@ -20,7 +20,7 @@ class ReversedPagesAdapter(
|
||||
parent: ViewGroup,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) = ReversedPageHolder(
|
||||
binding = ItemPageBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
import org.koitharu.kotatsu.reader.ui.pager.BaseReader
|
||||
@@ -26,7 +26,7 @@ import kotlin.math.absoluteValue
|
||||
class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
|
||||
|
||||
@Inject
|
||||
lateinit var networkStateObserver: NetworkStateObserver
|
||||
lateinit var networkState: NetworkState
|
||||
|
||||
private var pagerAdapter: ReversedPagesAdapter? = null
|
||||
|
||||
@@ -41,7 +41,7 @@ class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
|
||||
pagerAdapter = ReversedPagesAdapter(
|
||||
viewModel.pageLoader,
|
||||
viewModel.readerSettings,
|
||||
networkStateObserver,
|
||||
networkState,
|
||||
exceptionResolver,
|
||||
)
|
||||
with(binding.pager) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.ItemPageBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -22,7 +22,7 @@ open class PageHolder(
|
||||
binding: ItemPageBinding,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) : BasePageHolder<ItemPageBinding>(binding, loader, settings, networkState, exceptionResolver),
|
||||
View.OnClickListener {
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
import org.koitharu.kotatsu.reader.ui.pager.BaseReader
|
||||
@@ -25,7 +25,7 @@ import kotlin.math.absoluteValue
|
||||
class PagerReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
|
||||
|
||||
@Inject
|
||||
lateinit var networkStateObserver: NetworkStateObserver
|
||||
lateinit var networkState: NetworkState
|
||||
|
||||
private var pagesAdapter: PagesAdapter? = null
|
||||
|
||||
@@ -40,7 +40,7 @@ class PagerReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
|
||||
pagesAdapter = PagesAdapter(
|
||||
viewModel.pageLoader,
|
||||
viewModel.readerSettings,
|
||||
networkStateObserver,
|
||||
networkState,
|
||||
exceptionResolver,
|
||||
)
|
||||
with(binding.pager) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.reader.ui.pager.standard
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.ItemPageBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -12,15 +12,15 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
||||
class PagesAdapter(
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkStateObserver: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) : BaseReaderAdapter<PageHolder>(loader, settings, networkStateObserver, exceptionResolver) {
|
||||
) : BaseReaderAdapter<PageHolder>(loader, settings, networkState, exceptionResolver) {
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) = PageHolder(
|
||||
binding = ItemPageBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.reader.ui.pager.webtoon
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.ItemPageWebtoonBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -12,7 +12,7 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
||||
class WebtoonAdapter(
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) : BaseReaderAdapter<WebtoonHolder>(loader, settings, networkState, exceptionResolver) {
|
||||
|
||||
@@ -20,7 +20,7 @@ class WebtoonAdapter(
|
||||
parent: ViewGroup,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) = WebtoonHolder(
|
||||
binding = ItemPageWebtoonBinding.inflate(
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import com.davemorrissey.labs.subscaleview.decoder.SkiaPooledImageRegionDecoder
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.ItemPageWebtoonBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderSettings
|
||||
@@ -25,7 +25,7 @@ class WebtoonHolder(
|
||||
binding: ItemPageWebtoonBinding,
|
||||
loader: PageLoader,
|
||||
settings: ReaderSettings,
|
||||
networkState: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
exceptionResolver: ExceptionResolver,
|
||||
) : BasePageHolder<ItemPageWebtoonBinding>(binding, loader, settings, networkState, exceptionResolver),
|
||||
View.OnClickListener {
|
||||
|
||||
@@ -7,7 +7,7 @@ import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.databinding.FragmentReaderWebtoonBinding
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
import org.koitharu.kotatsu.reader.ui.pager.BaseReader
|
||||
@@ -22,7 +22,7 @@ import javax.inject.Inject
|
||||
class WebtoonReaderFragment : BaseReader<FragmentReaderWebtoonBinding>() {
|
||||
|
||||
@Inject
|
||||
lateinit var networkStateObserver: NetworkStateObserver
|
||||
lateinit var networkState: NetworkState
|
||||
|
||||
private val scrollInterpolator = AccelerateDecelerateInterpolator()
|
||||
private var webtoonAdapter: WebtoonAdapter? = null
|
||||
@@ -37,7 +37,7 @@ class WebtoonReaderFragment : BaseReader<FragmentReaderWebtoonBinding>() {
|
||||
webtoonAdapter = WebtoonAdapter(
|
||||
viewModel.pageLoader,
|
||||
viewModel.readerSettings,
|
||||
networkStateObserver,
|
||||
networkState,
|
||||
exceptionResolver,
|
||||
)
|
||||
with(binding.recyclerView) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.os.NetworkStateObserver
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsFlow
|
||||
@@ -46,14 +46,14 @@ class ShelfViewModel @Inject constructor(
|
||||
private val favouritesRepository: FavouritesRepository,
|
||||
private val trackingRepository: TrackingRepository,
|
||||
private val settings: AppSettings,
|
||||
networkStateObserver: NetworkStateObserver,
|
||||
networkState: NetworkState,
|
||||
) : BaseViewModel(), ListExtraProvider {
|
||||
|
||||
val onActionDone = SingleLiveEvent<ReversibleAction>()
|
||||
|
||||
val content: LiveData<List<ListModel>> = combine(
|
||||
settings.observeAsFlow(AppSettings.KEY_SHELF_SECTIONS) { shelfSections },
|
||||
networkStateObserver,
|
||||
networkState,
|
||||
repository.observeShelfContent(),
|
||||
) { sections, isConnected, content ->
|
||||
mapList(content, sections, isConnected)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
abstract class MediatorStateFlow<T> : StateFlow<T> {
|
||||
|
||||
@Suppress("LeakingThis")
|
||||
private val delegate = MutableStateFlow(initialValue)
|
||||
private val collectors = AtomicInteger(0)
|
||||
|
||||
protected abstract val initialValue: T
|
||||
|
||||
final override val replayCache: List<T>
|
||||
get() = delegate.replayCache
|
||||
|
||||
final override val value: T
|
||||
get() = delegate.value
|
||||
|
||||
final override suspend fun collect(collector: FlowCollector<T>): Nothing {
|
||||
try {
|
||||
if (collectors.getAndIncrement() == 0) {
|
||||
onActive()
|
||||
}
|
||||
delegate.collect(collector)
|
||||
} finally {
|
||||
if (collectors.decrementAndGet() == 0) {
|
||||
onInactive()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun publishValue(v: T) {
|
||||
delegate.value = v
|
||||
}
|
||||
|
||||
abstract fun onActive()
|
||||
|
||||
abstract fun onInactive()
|
||||
}
|
||||
Reference in New Issue
Block a user