Skip to content

Commit 9dd70bd

Browse files
authored
sync code (#55)
1 parent 1d61de9 commit 9dd70bd

File tree

9 files changed

+54
-25
lines changed

9 files changed

+54
-25
lines changed

app/src/main/java/com/hoc/flowmvi/core/CoreModule.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.hoc.flowmvi.core
22

3-
import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
3+
import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
44
import dagger.Binds
55
import dagger.Module
66
import dagger.hilt.InstallIn
@@ -12,5 +12,5 @@ import javax.inject.Singleton
1212
internal abstract class CoreModule {
1313
@Binds
1414
@Singleton
15-
abstract fun coroutineDispatchers(impl: DefaultCoroutineDispatchers): CoroutineDispatchers
15+
abstract fun coroutineDispatchers(impl: DefaultCoroutineDispatchers): AppCoroutineDispatchers
1616
}
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.hoc.flowmvi.core
22

3-
import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
3+
import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
44
import kotlinx.coroutines.CoroutineDispatcher
55
import kotlinx.coroutines.Dispatchers
66
import javax.inject.Inject
77

8-
internal class DefaultCoroutineDispatchers @Inject constructor() : CoroutineDispatchers {
9-
override val main: CoroutineDispatcher = Dispatchers.Main
10-
override val io: CoroutineDispatcher = Dispatchers.IO
8+
internal class DefaultCoroutineDispatchers @Inject constructor() : AppCoroutineDispatchers {
9+
override val main: CoroutineDispatcher get() = Dispatchers.Main
10+
override val io: CoroutineDispatcher get() = Dispatchers.IO
11+
override val mainImmediate: CoroutineDispatcher get() = Dispatchers.Main.immediate
12+
override val default: CoroutineDispatcher get() = Dispatchers.Default
1113
}

core/src/main/java/com/hoc/flowmvi/core/dispatchers/CoroutineDispatchers.kt renamed to core/src/main/java/com/hoc/flowmvi/core/dispatchers/AppCoroutineDispatchers.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package com.hoc.flowmvi.core.dispatchers
22

33
import kotlinx.coroutines.CoroutineDispatcher
44

5-
interface CoroutineDispatchers {
5+
interface AppCoroutineDispatchers {
66
val main: CoroutineDispatcher
77
val io: CoroutineDispatcher
8+
val mainImmediate: CoroutineDispatcher
9+
val default: CoroutineDispatcher
810
}

data/src/main/java/com/hoc/flowmvi/data/UserRepositoryImpl.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import arrow.core.leftWiden
66
import arrow.core.right
77
import arrow.core.valueOr
88
import com.hoc.flowmvi.core.Mapper
9-
import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
9+
import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
1010
import com.hoc.flowmvi.core.retrySuspend
1111
import com.hoc.flowmvi.data.remote.UserApiService
1212
import com.hoc.flowmvi.data.remote.UserBody
@@ -33,7 +33,7 @@ import arrow.core.Either.Companion.catch as catchEither
3333
@ExperimentalTime
3434
internal class UserRepositoryImpl @Inject constructor(
3535
private val userApiService: UserApiService,
36-
private val dispatchers: CoroutineDispatchers,
36+
private val dispatchers: AppCoroutineDispatchers,
3737
private val responseToDomain: UserResponseToUserDomainMapperType,
3838
private val domainToBody: Mapper<User, UserBody>,
3939
private val errorMapper: Mapper<Throwable, UserError>,

data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplRealAPITest.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.hoc.flowmvi.data
22

33
import android.util.Log
4-
import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
4+
import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
55
import com.hoc.flowmvi.domain.repository.UserRepository
66
import com.hoc.flowmvi.test_utils.getOrThrow
77
import kotlinx.coroutines.CoroutineDispatcher
@@ -34,10 +34,12 @@ class UserRepositoryImplRealAPITest : KoinTest {
3434
modules(
3535
dataModule,
3636
module {
37-
factory<CoroutineDispatchers> {
38-
object : CoroutineDispatchers {
37+
factory<AppCoroutineDispatchers> {
38+
object : AppCoroutineDispatchers {
3939
override val main: CoroutineDispatcher get() = Main
4040
override val io: CoroutineDispatcher get() = IO
41+
override val mainImmediate: CoroutineDispatcher get() = Main.immediate
42+
override val default: CoroutineDispatcher get() = IO
4143
}
4244
}
4345
}

feature-main/src/main/java/com/hoc/flowmvi/ui/main/MainVM.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package com.hoc.flowmvi.ui.main
22

33
import androidx.lifecycle.viewModelScope
44
import arrow.core.flatMap
5+
import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
56
import com.hoc.flowmvi.domain.usecase.GetUsersUseCase
67
import com.hoc.flowmvi.domain.usecase.RefreshGetUsersUseCase
78
import com.hoc.flowmvi.domain.usecase.RemoveUserUseCase
89
import com.hoc.flowmvi.mvi_base.AbstractMviViewModel
10+
import com.hoc081098.flowext.defer
911
import com.hoc081098.flowext.flatMapFirst
12+
import com.hoc081098.flowext.flowFromSuspend
1013
import com.hoc081098.flowext.startWith
1114
import dagger.hilt.android.lifecycle.HiltViewModel
1215
import kotlinx.coroutines.FlowPreview
@@ -15,13 +18,11 @@ import kotlinx.coroutines.flow.SharingStarted
1518
import kotlinx.coroutines.flow.StateFlow
1619
import kotlinx.coroutines.flow.asFlow
1720
import kotlinx.coroutines.flow.catch
18-
import kotlinx.coroutines.flow.emitAll
1921
import kotlinx.coroutines.flow.filter
2022
import kotlinx.coroutines.flow.filterIsInstance
2123
import kotlinx.coroutines.flow.filterNot
2224
import kotlinx.coroutines.flow.flatMapConcat
2325
import kotlinx.coroutines.flow.flatMapMerge
24-
import kotlinx.coroutines.flow.flow
2526
import kotlinx.coroutines.flow.map
2627
import kotlinx.coroutines.flow.merge
2728
import kotlinx.coroutines.flow.onEach
@@ -37,7 +38,8 @@ class MainVM @Inject constructor(
3738
private val getUsersUseCase: GetUsersUseCase,
3839
private val refreshGetUsers: RefreshGetUsersUseCase,
3940
private val removeUser: RemoveUserUseCase,
40-
) : AbstractMviViewModel<ViewIntent, ViewState, SingleEvent>() {
41+
appCoroutineDispatchers: AppCoroutineDispatchers,
42+
) : AbstractMviViewModel<ViewIntent, ViewState, SingleEvent>(appCoroutineDispatchers) {
4143

4244
override val viewState: StateFlow<ViewState>
4345

@@ -117,11 +119,10 @@ class MainVM @Inject constructor(
117119
.log("Intent")
118120
.map { it.user }
119121
.flatMapMerge { userItem ->
120-
flow {
122+
flowFromSuspend {
121123
userItem
122124
.toDomain()
123125
.flatMap { removeUser(it) }
124-
.let { emit(it) }
125126
}
126127
.map { result ->
127128
result.fold(
@@ -134,5 +135,3 @@ class MainVM @Inject constructor(
134135
)
135136
}
136137
}
137-
138-
private fun <T> defer(flowFactory: () -> Flow<T>): Flow<T> = flow { emitAll(flowFactory()) }

mvi/mvi-base/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ dependencies {
3838
implementation(deps.coroutines.core)
3939

4040
implementation(coreUi)
41+
implementation(core)
4142
implementation(deps.timber)
4243

4344
addUnitTest()

mvi/mvi-base/src/main/java/com/hoc/flowmvi/mvi_base/AbstractMviViewModel.kt

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.hoc.flowmvi.mvi_base
22

33
import android.os.Build
4+
import androidx.annotation.CallSuper
45
import androidx.lifecycle.ViewModel
56
import androidx.lifecycle.viewModelScope
7+
import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
68
import kotlinx.coroutines.channels.Channel
9+
import kotlinx.coroutines.currentCoroutineContext
710
import kotlinx.coroutines.flow.Flow
811
import kotlinx.coroutines.flow.MutableSharedFlow
912
import kotlinx.coroutines.flow.SharedFlow
@@ -13,12 +16,17 @@ import kotlinx.coroutines.flow.onEach
1316
import kotlinx.coroutines.flow.receiveAsFlow
1417
import kotlinx.coroutines.flow.shareIn
1518
import kotlinx.coroutines.flow.stateIn
19+
import kotlinx.coroutines.withContext
1620
import timber.log.Timber
21+
import kotlin.LazyThreadSafetyMode.PUBLICATION
22+
import kotlin.coroutines.ContinuationInterceptor
1723

18-
abstract class AbstractMviViewModel<I : MviIntent, S : MviViewState, E : MviSingleEvent> :
24+
abstract class AbstractMviViewModel<I : MviIntent, S : MviViewState, E : MviSingleEvent>(
25+
private val appCoroutineDispatchers: AppCoroutineDispatchers,
26+
) :
1927
MviViewModel<I, S, E>, ViewModel() {
20-
protected val logTag by lazy(LazyThreadSafetyMode.PUBLICATION) {
21-
this::class.java.simpleName.let { tag ->
28+
protected val logTag by lazy(PUBLICATION) {
29+
this::class.java.simpleName.let { tag: String ->
2230
// Tag length limit was removed in API 26.
2331
if (tag.length <= MAX_TAG_LENGTH || Build.VERSION.SDK_INT >= 26) {
2432
tag
@@ -34,9 +42,22 @@ abstract class AbstractMviViewModel<I : MviIntent, S : MviViewState, E : MviSing
3442
final override val singleEvent: Flow<E> get() = eventChannel.receiveAsFlow()
3543
final override suspend fun processIntent(intent: I) = intentMutableFlow.emit(intent)
3644

45+
@CallSuper
46+
override fun onCleared() {
47+
super.onCleared()
48+
eventChannel.close()
49+
}
50+
3751
// Send event and access intent flow.
3852

39-
protected suspend fun sendEvent(event: E) = eventChannel.send(event)
53+
protected suspend fun sendEvent(event: E) {
54+
if (currentCoroutineContext()[ContinuationInterceptor] === appCoroutineDispatchers.mainImmediate) {
55+
eventChannel.send(event)
56+
} else {
57+
withContext(appCoroutineDispatchers.mainImmediate) { eventChannel.send(event) }
58+
}
59+
}
60+
4061
protected val intentFlow: SharedFlow<I> get() = intentMutableFlow
4162

4263
// Extensions on Flow using viewModelScope.
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package com.hoc.flowmvi.test_utils
22

3-
import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
3+
import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
44
import kotlinx.coroutines.CoroutineDispatcher
55
import kotlinx.coroutines.ExperimentalCoroutinesApi
66
import kotlinx.coroutines.test.TestCoroutineDispatcher
77

88
@ExperimentalCoroutinesApi
99
class TestDispatchers(testCoroutineDispatcher: TestCoroutineDispatcher) :
10-
CoroutineDispatchers {
10+
AppCoroutineDispatchers {
1111
override val main: CoroutineDispatcher = testCoroutineDispatcher
1212
override val io: CoroutineDispatcher = testCoroutineDispatcher
13+
override val mainImmediate: CoroutineDispatcher = testCoroutineDispatcher
14+
override val default: CoroutineDispatcher = testCoroutineDispatcher
1315
}

0 commit comments

Comments
 (0)