Replace LiveData with StateFlow

This commit is contained in:
Koitharu
2023-05-27 12:25:49 +03:00
parent 47f346b42c
commit 5a0c54e00f
147 changed files with 1047 additions and 1039 deletions

View File

@@ -1,16 +1,16 @@
package org.koitharu.kotatsu.tracker.domain
import androidx.annotation.VisibleForTesting
import javax.inject.Inject
import org.koitharu.kotatsu.core.model.getPreferredBranch
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.history.data.HistoryRepository
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.tracker.domain.model.MangaTracking
import org.koitharu.kotatsu.tracker.domain.model.MangaUpdates
import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels
import org.koitharu.kotatsu.tracker.work.TrackingItem
import javax.inject.Inject
class Tracker @Inject constructor(
private val settings: AppSettings,
@@ -114,9 +114,11 @@ class Tracker @Inject constructor(
newChapters.isEmpty() -> {
MangaUpdates(manga, emptyList(), isValid = chapters.lastOrNull()?.id == track.lastChapterId)
}
newChapters.size == chapters.size -> {
MangaUpdates(manga, emptyList(), isValid = false)
}
else -> {
MangaUpdates(manga, newChapters, isValid = true)
}

View File

@@ -18,6 +18,8 @@ import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener
import org.koitharu.kotatsu.core.ui.list.decor.TypedSpacingItemDecoration
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.FragmentFeedBinding
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
@@ -76,11 +78,11 @@ class FeedFragment :
)
viewModel.content.observe(viewLifecycleOwner, this::onListChanged)
viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
viewModel.onFeedCleared.observe(viewLifecycleOwner) {
onFeedCleared()
}
TrackWorker.getIsRunningLiveData(binding.root.context.applicationContext)
TrackWorker.observeIsRunning(binding.root.context.applicationContext)
.observe(viewLifecycleOwner, this::onIsTrackerRunningChanged)
}

View File

@@ -4,12 +4,15 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.ui.model.DateTimeAgo
import org.koitharu.kotatsu.core.util.SingleLiveEvent
import org.koitharu.kotatsu.core.util.asFlowLiveData
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.core.util.ext.daysDiff
import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.ListModel
@@ -32,7 +35,7 @@ class FeedViewModel @Inject constructor(
private val limit = MutableStateFlow(PAGE_SIZE)
private val isReady = AtomicBoolean(false)
val onFeedCleared = SingleLiveEvent<Unit>()
val onFeedCleared = MutableEventFlow<Unit>()
val content = repository.observeTrackingLog(limit)
.map { list ->
if (list.isEmpty()) {
@@ -48,7 +51,7 @@ class FeedViewModel @Inject constructor(
isReady.set(true)
list.mapList()
}
}.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
fun clearFeed(clearCounters: Boolean) {
launchLoadingJob(Dispatchers.Default) {
@@ -56,7 +59,7 @@ class FeedViewModel @Inject constructor(
if (clearCounters) {
repository.clearCounters()
}
onFeedCleared.emitCall(Unit)
onFeedCleared.call(Unit)
}
}

View File

@@ -3,18 +3,20 @@ package org.koitharu.kotatsu.tracker.ui.updates
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.core.util.asFlowLiveData
import org.koitharu.kotatsu.core.util.ext.onFirst
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.history.domain.PROGRESS_NONE
import org.koitharu.kotatsu.history.data.HistoryRepository
import org.koitharu.kotatsu.history.data.PROGRESS_NONE
import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.ListModel
@@ -38,7 +40,7 @@ class UpdatesViewModel @Inject constructor(
override val content = combine(
repository.observeUpdatedManga(),
listModeFlow,
listMode,
) { mangaMap, mode ->
when {
mangaMap.isEmpty() -> listOf(
@@ -58,7 +60,7 @@ class UpdatesViewModel @Inject constructor(
loadingCounter.decrement()
}.catch {
emit(listOf(it.toErrorState(canRetry = false)))
}.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
override fun onRefresh() = Unit

View File

@@ -11,8 +11,7 @@ import androidx.core.app.NotificationCompat.VISIBILITY_SECRET
import androidx.core.app.PendingIntentCompat
import androidx.core.content.ContextCompat
import androidx.hilt.work.HiltWorker
import androidx.lifecycle.LiveData
import androidx.lifecycle.map
import androidx.lifecycle.asFlow
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.CoroutineWorker
@@ -35,6 +34,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R
@@ -263,11 +264,13 @@ class TrackWorker @AssistedInject constructor(
WorkManager.getInstance(context).enqueue(request)
}
fun getIsRunningLiveData(context: Context): LiveData<Boolean> {
fun observeIsRunning(context: Context): Flow<Boolean> {
val query = WorkQuery.Builder.fromTags(listOf(TAG, TAG_ONESHOT)).build()
return WorkManager.getInstance(context).getWorkInfosLiveData(query).map { works ->
works.any { x -> x.state == WorkInfo.State.RUNNING }
}
return WorkManager.getInstance(context).getWorkInfosLiveData(query)
.asFlow()
.map { works ->
works.any { x -> x.state == WorkInfo.State.RUNNING }
}
}
}
}