Unified CoroutineDispatcher

This commit is contained in:
Ash 2022-05-16 10:57:40 +08:00
parent a1021c3c3f
commit 962e0ee8dc
4 changed files with 51 additions and 30 deletions

View File

@ -5,12 +5,14 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.ash.reader.R import me.ash.reader.R
import me.ash.reader.data.entity.Account import me.ash.reader.data.entity.Account
import me.ash.reader.data.entity.GroupWithFeed import me.ash.reader.data.entity.GroupWithFeed
import me.ash.reader.data.module.DispatcherDefault
import me.ash.reader.data.module.DispatcherIO
import me.ash.reader.data.repository.AccountRepository import me.ash.reader.data.repository.AccountRepository
import me.ash.reader.data.repository.OpmlRepository import me.ash.reader.data.repository.OpmlRepository
import me.ash.reader.data.repository.RssRepository import me.ash.reader.data.repository.RssRepository
@ -24,6 +26,10 @@ class FeedsViewModel @Inject constructor(
private val rssRepository: RssRepository, private val rssRepository: RssRepository,
private val opmlRepository: OpmlRepository, private val opmlRepository: OpmlRepository,
private val stringsRepository: StringsRepository, private val stringsRepository: StringsRepository,
@DispatcherDefault
private val dispatcherDefault: CoroutineDispatcher,
@DispatcherIO
private val dispatcherIO: CoroutineDispatcher,
) : ViewModel() { ) : ViewModel() {
private val _viewState = MutableStateFlow(FeedsViewState()) private val _viewState = MutableStateFlow(FeedsViewState())
val viewState: StateFlow<FeedsViewState> = _viewState.asStateFlow() val viewState: StateFlow<FeedsViewState> = _viewState.asStateFlow()
@ -38,7 +44,7 @@ class FeedsViewModel @Inject constructor(
} }
private fun fetchAccount() { private fun fetchAccount() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
_viewState.update { _viewState.update {
it.copy( it.copy(
account = accountRepository.getCurrentAccount() account = accountRepository.getCurrentAccount()
@ -48,7 +54,7 @@ class FeedsViewModel @Inject constructor(
} }
private fun exportAsOpml(callback: (String) -> Unit = {}) { private fun exportAsOpml(callback: (String) -> Unit = {}) {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(dispatcherDefault) {
try { try {
callback(opmlRepository.saveToString()) callback(opmlRepository.saveToString())
} catch (e: Exception) { } catch (e: Exception) {
@ -58,7 +64,7 @@ class FeedsViewModel @Inject constructor(
} }
private fun fetchData(filterState: FilterState) { private fun fetchData(filterState: FilterState) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
pullFeeds( pullFeeds(
isStarred = filterState.filter.isStarred(), isStarred = filterState.filter.isStarred(),
isUnread = filterState.filter.isUnread(), isUnread = filterState.filter.isUnread(),
@ -118,7 +124,7 @@ class FeedsViewModel @Inject constructor(
} }
}.catch { }.catch {
Log.e("RLog", "catch in articleRepository.pullFeeds(): ${it.message}") Log.e("RLog", "catch in articleRepository.pullFeeds(): ${it.message}")
}.flowOn(Dispatchers.Default).collect() }.flowOn(dispatcherDefault).collect()
} }
private fun scrollToItem(index: Int) { private fun scrollToItem(index: Int) {

View File

@ -7,8 +7,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.ExperimentalPagerApi
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@ -17,6 +17,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import me.ash.reader.data.entity.Feed import me.ash.reader.data.entity.Feed
import me.ash.reader.data.entity.Group import me.ash.reader.data.entity.Group
import me.ash.reader.data.module.DispatcherIO
import me.ash.reader.data.module.DispatcherMain
import me.ash.reader.data.repository.RssRepository import me.ash.reader.data.repository.RssRepository
import javax.inject.Inject import javax.inject.Inject
@ -27,12 +29,16 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class FeedOptionViewModel @Inject constructor( class FeedOptionViewModel @Inject constructor(
private val rssRepository: RssRepository, private val rssRepository: RssRepository,
@DispatcherMain
private val dispatcherMain: CoroutineDispatcher,
@DispatcherIO
private val dispatcherIO: CoroutineDispatcher,
) : ViewModel() { ) : ViewModel() {
private val _viewState = MutableStateFlow(FeedOptionViewState()) private val _viewState = MutableStateFlow(FeedOptionViewState())
val viewState: StateFlow<FeedOptionViewState> = _viewState.asStateFlow() val viewState: StateFlow<FeedOptionViewState> = _viewState.asStateFlow()
init { init {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().pullGroups().collect { groups -> rssRepository.get().pullGroups().collect { groups ->
_viewState.update { _viewState.update {
it.copy( it.copy(
@ -121,7 +127,7 @@ class FeedOptionViewModel @Inject constructor(
} }
private fun selectedGroup(groupId: String) { private fun selectedGroup(groupId: String) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
_viewState.value.feed?.let { _viewState.value.feed?.let {
rssRepository.get().updateFeed( rssRepository.get().updateFeed(
it.copy( it.copy(
@ -134,7 +140,7 @@ class FeedOptionViewModel @Inject constructor(
} }
private fun changeParseFullContentPreset() { private fun changeParseFullContentPreset() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
_viewState.value.feed?.let { _viewState.value.feed?.let {
rssRepository.get().updateFeed( rssRepository.get().updateFeed(
it.copy( it.copy(
@ -147,7 +153,7 @@ class FeedOptionViewModel @Inject constructor(
} }
private fun changeAllowNotificationPreset() { private fun changeAllowNotificationPreset() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
_viewState.value.feed?.let { _viewState.value.feed?.let {
rssRepository.get().updateFeed( rssRepository.get().updateFeed(
it.copy( it.copy(
@ -161,9 +167,9 @@ class FeedOptionViewModel @Inject constructor(
private fun delete(callback: () -> Unit = {}) { private fun delete(callback: () -> Unit = {}) {
_viewState.value.feed?.let { _viewState.value.feed?.let {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().deleteFeed(it) rssRepository.get().deleteFeed(it)
withContext(Dispatchers.Main) { withContext(dispatcherMain) {
callback() callback()
} }
} }
@ -204,9 +210,9 @@ class FeedOptionViewModel @Inject constructor(
private fun clear(callback: () -> Unit = {}) { private fun clear(callback: () -> Unit = {}) {
_viewState.value.feed?.let { _viewState.value.feed?.let {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().deleteArticles(feed = it) rssRepository.get().deleteArticles(feed = it)
withContext(Dispatchers.Main) { withContext(dispatcherMain) {
callback() callback()
} }
} }

View File

@ -7,8 +7,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.ExperimentalPagerApi
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@ -16,6 +16,8 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import me.ash.reader.data.entity.Group import me.ash.reader.data.entity.Group
import me.ash.reader.data.module.DispatcherIO
import me.ash.reader.data.module.DispatcherMain
import me.ash.reader.data.repository.RssRepository import me.ash.reader.data.repository.RssRepository
import javax.inject.Inject import javax.inject.Inject
@ -26,12 +28,16 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class GroupOptionViewModel @Inject constructor( class GroupOptionViewModel @Inject constructor(
private val rssRepository: RssRepository, private val rssRepository: RssRepository,
@DispatcherMain
private val dispatcherMain: CoroutineDispatcher,
@DispatcherIO
private val dispatcherIO: CoroutineDispatcher,
) : ViewModel() { ) : ViewModel() {
private val _viewState = MutableStateFlow(GroupOptionViewState()) private val _viewState = MutableStateFlow(GroupOptionViewState())
val viewState: StateFlow<GroupOptionViewState> = _viewState.asStateFlow() val viewState: StateFlow<GroupOptionViewState> = _viewState.asStateFlow()
init { init {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().pullGroups().collect { groups -> rssRepository.get().pullGroups().collect { groups ->
_viewState.update { _viewState.update {
it.copy( it.copy(
@ -106,9 +112,9 @@ class GroupOptionViewModel @Inject constructor(
private fun allAllowNotification(isNotification: Boolean, callback: () -> Unit = {}) { private fun allAllowNotification(isNotification: Boolean, callback: () -> Unit = {}) {
_viewState.value.group?.let { _viewState.value.group?.let {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().groupAllowNotification(it, isNotification) rssRepository.get().groupAllowNotification(it, isNotification)
withContext(Dispatchers.Main) { withContext(dispatcherMain) {
callback() callback()
} }
} }
@ -125,9 +131,9 @@ class GroupOptionViewModel @Inject constructor(
private fun allParseFullContent(isFullContent: Boolean, callback: () -> Unit = {}) { private fun allParseFullContent(isFullContent: Boolean, callback: () -> Unit = {}) {
_viewState.value.group?.let { _viewState.value.group?.let {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().groupParseFullContent(it, isFullContent) rssRepository.get().groupParseFullContent(it, isFullContent)
withContext(Dispatchers.Main) { withContext(dispatcherMain) {
callback() callback()
} }
} }
@ -144,9 +150,9 @@ class GroupOptionViewModel @Inject constructor(
private fun delete(callback: () -> Unit = {}) { private fun delete(callback: () -> Unit = {}) {
_viewState.value.group?.let { _viewState.value.group?.let {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().deleteGroup(it) rssRepository.get().deleteGroup(it)
withContext(Dispatchers.Main) { withContext(dispatcherMain) {
callback() callback()
} }
} }
@ -179,9 +185,9 @@ class GroupOptionViewModel @Inject constructor(
private fun clear(callback: () -> Unit = {}) { private fun clear(callback: () -> Unit = {}) {
_viewState.value.group?.let { _viewState.value.group?.let {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().deleteArticles(group = it) rssRepository.get().deleteArticles(group = it)
withContext(Dispatchers.Main) { withContext(dispatcherMain) {
callback() callback()
} }
} }
@ -191,9 +197,9 @@ class GroupOptionViewModel @Inject constructor(
private fun allMoveToGroup(callback: () -> Unit) { private fun allMoveToGroup(callback: () -> Unit) {
_viewState.value.group?.let { group -> _viewState.value.group?.let { group ->
_viewState.value.targetGroup?.let { targetGroup -> _viewState.value.targetGroup?.let { targetGroup ->
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
rssRepository.get().groupMoveToTargetGroup(group, targetGroup) rssRepository.get().groupMoveToTargetGroup(group, targetGroup)
withContext(Dispatchers.Main) { withContext(dispatcherMain) {
callback() callback()
} }
} }

View File

@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.ExperimentalPagerApi
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -14,6 +14,7 @@ import me.ash.reader.R
import me.ash.reader.data.entity.Article import me.ash.reader.data.entity.Article
import me.ash.reader.data.entity.Feed import me.ash.reader.data.entity.Feed
import me.ash.reader.data.entity.Group import me.ash.reader.data.entity.Group
import me.ash.reader.data.module.DispatcherIO
import me.ash.reader.data.repository.OpmlRepository import me.ash.reader.data.repository.OpmlRepository
import me.ash.reader.data.repository.RssHelper import me.ash.reader.data.repository.RssHelper
import me.ash.reader.data.repository.RssRepository import me.ash.reader.data.repository.RssRepository
@ -29,6 +30,8 @@ class SubscribeViewModel @Inject constructor(
private val rssRepository: RssRepository, private val rssRepository: RssRepository,
private val rssHelper: RssHelper, private val rssHelper: RssHelper,
private val stringsRepository: StringsRepository, private val stringsRepository: StringsRepository,
@DispatcherIO
private val dispatcherIO: CoroutineDispatcher,
) : ViewModel() { ) : ViewModel() {
private val _viewState = MutableStateFlow(SubscribeViewState()) private val _viewState = MutableStateFlow(SubscribeViewState())
val viewState: StateFlow<SubscribeViewState> = _viewState.asStateFlow() val viewState: StateFlow<SubscribeViewState> = _viewState.asStateFlow()
@ -77,7 +80,7 @@ class SubscribeViewModel @Inject constructor(
} }
private fun importFromInputStream(inputStream: InputStream) { private fun importFromInputStream(inputStream: InputStream) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
try { try {
opmlRepository.saveToDatabase(inputStream) opmlRepository.saveToDatabase(inputStream)
rssRepository.get().doSync() rssRepository.get().doSync()
@ -90,7 +93,7 @@ class SubscribeViewModel @Inject constructor(
private fun subscribe() { private fun subscribe() {
val feed = _viewState.value.feed ?: return val feed = _viewState.value.feed ?: return
val articles = _viewState.value.articles val articles = _viewState.value.articles
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
val groupId = async { val groupId = async {
_viewState.value.selectedGroupId _viewState.value.selectedGroupId
} }
@ -145,7 +148,7 @@ class SubscribeViewModel @Inject constructor(
private fun search() { private fun search() {
searchJob?.cancel() searchJob?.cancel()
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(dispatcherIO) {
try { try {
_viewState.update { _viewState.update {
it.copy( it.copy(