diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 232f8f16..cb99164d 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -25,7 +25,6 @@
-
diff --git a/app/src/main/java/com/hoc/flowmvi/core/CoreModule.kt b/app/src/main/java/com/hoc/flowmvi/core/CoreModule.kt
index 93ac93a3..fa28128c 100644
--- a/app/src/main/java/com/hoc/flowmvi/core/CoreModule.kt
+++ b/app/src/main/java/com/hoc/flowmvi/core/CoreModule.kt
@@ -1,12 +1,14 @@
package com.hoc.flowmvi.core
-import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
+import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
import com.hoc.flowmvi.core_ui.navigator.Navigator
+import org.koin.core.module.dsl.bind
+import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
@JvmField
val coreModule = module {
- single { DefaultCoroutineDispatchers() }
+ singleOf(::DefaultAppCoroutineDispatchers) { bind() }
- single { NavigatorImpl(add = get(), search = get()) }
+ singleOf(::NavigatorImpl) { bind() }
}
diff --git a/app/src/main/java/com/hoc/flowmvi/core/DefaultAppCoroutineDispatchers.kt b/app/src/main/java/com/hoc/flowmvi/core/DefaultAppCoroutineDispatchers.kt
new file mode 100644
index 00000000..45a25b40
--- /dev/null
+++ b/app/src/main/java/com/hoc/flowmvi/core/DefaultAppCoroutineDispatchers.kt
@@ -0,0 +1,10 @@
+package com.hoc.flowmvi.core
+
+import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
+import kotlinx.coroutines.Dispatchers
+
+internal class DefaultAppCoroutineDispatchers : AppCoroutineDispatchers {
+ override val main get() = Dispatchers.Main
+ override val mainImmediate get() = Dispatchers.Main.immediate
+ override val io get() = Dispatchers.IO
+}
diff --git a/app/src/main/java/com/hoc/flowmvi/core/DefaultCoroutineDispatchers.kt b/app/src/main/java/com/hoc/flowmvi/core/DefaultCoroutineDispatchers.kt
deleted file mode 100644
index 7e157ddb..00000000
--- a/app/src/main/java/com/hoc/flowmvi/core/DefaultCoroutineDispatchers.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.hoc.flowmvi.core
-
-import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.Dispatchers
-
-internal class DefaultCoroutineDispatchers : CoroutineDispatchers {
- override val main: CoroutineDispatcher = Dispatchers.Main
- override val io: CoroutineDispatcher = Dispatchers.IO
-}
diff --git a/app/src/test/java/com/hoc/flowmvi/CheckModulesTest.kt b/app/src/test/java/com/hoc/flowmvi/CheckModulesTest.kt
index 259fa6fc..71a3089f 100644
--- a/app/src/test/java/com/hoc/flowmvi/CheckModulesTest.kt
+++ b/app/src/test/java/com/hoc/flowmvi/CheckModulesTest.kt
@@ -3,7 +3,7 @@ package com.hoc.flowmvi
import androidx.lifecycle.SavedStateHandle
import com.hoc.flowmvi.test_utils.TestCoroutineDispatcherRule
import io.mockk.every
-import io.mockk.mockkClass
+import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import org.junit.Rule
@@ -22,12 +22,16 @@ import kotlin.time.ExperimentalTime
class CheckModulesTest : AutoCloseKoinTest() {
@get:Rule
val mockProvider = MockProviderRule.create { clazz ->
- mockkClass(clazz).also { o ->
- if (clazz == SavedStateHandle::class) {
- every { (o as SavedStateHandle).get(any()) } returns null
+ when (clazz) {
+ SavedStateHandle::class -> {
+ mockk() {
+ every { get(any()) } returns null
+ }
}
+ else -> error("Unknown class: $clazz")
}
}
+
@get:Rule
val coroutineRule = TestCoroutineDispatcherRule()
diff --git a/buildSrc/src/main/kotlin/deps.kt b/buildSrc/src/main/kotlin/deps.kt
index 3d479258..fa9a69ca 100644
--- a/buildSrc/src/main/kotlin/deps.kt
+++ b/buildSrc/src/main/kotlin/deps.kt
@@ -60,7 +60,7 @@ object deps {
}
object koin {
- private const val version = "3.2.0-beta-1"
+ private const val version = "3.2.0"
const val core = "io.insert-koin:koin-core:$version"
const val android = "io.insert-koin:koin-android:$version"
@@ -90,7 +90,7 @@ object deps {
}
}
- const val mockk = "io.mockk:mockk:1.12.3"
+ const val mockk = "io.mockk:mockk:1.12.4"
const val kotlinJUnit = "org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion"
}
}
diff --git a/core/src/main/java/com/hoc/flowmvi/core/dispatchers/CoroutineDispatchers.kt b/core/src/main/java/com/hoc/flowmvi/core/dispatchers/AppCoroutineDispatchers.kt
similarity index 66%
rename from core/src/main/java/com/hoc/flowmvi/core/dispatchers/CoroutineDispatchers.kt
rename to core/src/main/java/com/hoc/flowmvi/core/dispatchers/AppCoroutineDispatchers.kt
index 787c0e28..cc6b8281 100644
--- a/core/src/main/java/com/hoc/flowmvi/core/dispatchers/CoroutineDispatchers.kt
+++ b/core/src/main/java/com/hoc/flowmvi/core/dispatchers/AppCoroutineDispatchers.kt
@@ -2,7 +2,8 @@ package com.hoc.flowmvi.core.dispatchers
import kotlinx.coroutines.CoroutineDispatcher
-interface CoroutineDispatchers {
+interface AppCoroutineDispatchers {
val main: CoroutineDispatcher
+ val mainImmediate: CoroutineDispatcher
val io: CoroutineDispatcher
}
diff --git a/data/src/main/java/com/hoc/flowmvi/data/DataModule.kt b/data/src/main/java/com/hoc/flowmvi/data/DataModule.kt
index 45ade5ef..3852c7f2 100644
--- a/data/src/main/java/com/hoc/flowmvi/data/DataModule.kt
+++ b/data/src/main/java/com/hoc/flowmvi/data/DataModule.kt
@@ -14,6 +14,7 @@ import kotlinx.coroutines.FlowPreview
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.HttpLoggingInterceptor.Level
+import org.koin.core.module.dsl.singleOf
import org.koin.core.qualifier.named
import org.koin.dsl.module
import retrofit2.Retrofit
@@ -21,7 +22,8 @@ import retrofit2.converter.moshi.MoshiConverterFactory
import java.util.concurrent.TimeUnit
import kotlin.time.ExperimentalTime
-val BASE_URL_QUALIFIER = named("BASE_URL")
+internal val BASE_URL_QUALIFIER = named("BASE_URL")
+internal val ERROR_RESPONSE_JSON_ADAPTER = named("ERROR_RESPONSE_JSON_ADAPTER")
@JvmField
@FlowPreview
@@ -29,7 +31,7 @@ val BASE_URL_QUALIFIER = named("BASE_URL")
@ExperimentalTime
@ExperimentalCoroutinesApi
val dataModule = module {
- single { UserApiService(retrofit = get()) }
+ singleOf(UserApiService::invoke)
single {
provideRetrofit(
@@ -49,9 +51,9 @@ val dataModule = module {
factory { UserDomainToUserBodyMapper() }
- factory { get().adapter() }
+ factory(ERROR_RESPONSE_JSON_ADAPTER) { get().adapter() }
- factory { UserErrorMapper(errorResponseJsonAdapter = get()) }
+ factory { UserErrorMapper(get(ERROR_RESPONSE_JSON_ADAPTER)) }
single {
UserRepositoryImpl(
diff --git a/data/src/main/java/com/hoc/flowmvi/data/UserRepositoryImpl.kt b/data/src/main/java/com/hoc/flowmvi/data/UserRepositoryImpl.kt
index 73012e16..b9b7fce1 100644
--- a/data/src/main/java/com/hoc/flowmvi/data/UserRepositoryImpl.kt
+++ b/data/src/main/java/com/hoc/flowmvi/data/UserRepositoryImpl.kt
@@ -7,7 +7,7 @@ import arrow.core.leftWiden
import arrow.core.right
import arrow.core.valueOr
import com.hoc.flowmvi.core.Mapper
-import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
+import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
import com.hoc.flowmvi.data.remote.UserApiService
import com.hoc.flowmvi.data.remote.UserBody
import com.hoc.flowmvi.data.remote.UserResponse
@@ -39,7 +39,7 @@ import arrow.core.Either.Companion.catch as catchEither
@ExperimentalCoroutinesApi
internal class UserRepositoryImpl(
private val userApiService: UserApiService,
- private val dispatchers: CoroutineDispatchers,
+ private val dispatchers: AppCoroutineDispatchers,
private val responseToDomain: Mapper>,
private val domainToBody: Mapper,
private val errorMapper: Mapper,
diff --git a/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplRealAPITest.kt b/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplRealAPITest.kt
index 033c1ff4..c23917bf 100644
--- a/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplRealAPITest.kt
+++ b/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplRealAPITest.kt
@@ -1,7 +1,7 @@
package com.hoc.flowmvi.data
import android.util.Log
-import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
+import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
import com.hoc.flowmvi.domain.repository.UserRepository
import com.hoc.flowmvi.test_utils.getOrThrow
import kotlinx.coroutines.CoroutineDispatcher
@@ -38,10 +38,11 @@ class UserRepositoryImplRealAPITest : KoinTest {
modules(
dataModule,
module {
- factory {
- object : CoroutineDispatchers {
+ factory {
+ object : AppCoroutineDispatchers {
override val main: CoroutineDispatcher get() = Main
override val io: CoroutineDispatcher get() = IO
+ override val mainImmediate: CoroutineDispatcher get() = Main.immediate
}
}
}
diff --git a/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplTest.kt b/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplTest.kt
index f465a5dc..52e17ba0 100644
--- a/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplTest.kt
+++ b/data/src/test/java/com/hoc/flowmvi/data/UserRepositoryImplTest.kt
@@ -10,8 +10,8 @@ import com.hoc.flowmvi.data.remote.UserResponse
import com.hoc.flowmvi.domain.model.User
import com.hoc.flowmvi.domain.model.UserError
import com.hoc.flowmvi.domain.model.UserValidationError
+import com.hoc.flowmvi.test_utils.TestAppCoroutineDispatchers
import com.hoc.flowmvi.test_utils.TestCoroutineDispatcherRule
-import com.hoc.flowmvi.test_utils.TestDispatchers
import com.hoc.flowmvi.test_utils.getOrThrow
import com.hoc.flowmvi.test_utils.leftOrThrow
import com.hoc.flowmvi.test_utils.valueOrThrow
@@ -121,7 +121,7 @@ class UserRepositoryImplTest {
repo = UserRepositoryImpl(
userApiService = userApiService,
- dispatchers = TestDispatchers(coroutineRule.testDispatcher),
+ dispatchers = TestAppCoroutineDispatchers(coroutineRule.testDispatcher),
responseToDomain = responseToDomain,
domainToBody = domainToBody,
errorMapper = errorMapper
diff --git a/domain/src/main/java/com/hoc/flowmvi/domain/DomainModule.kt b/domain/src/main/java/com/hoc/flowmvi/domain/DomainModule.kt
index ef4f868f..d288eabb 100644
--- a/domain/src/main/java/com/hoc/flowmvi/domain/DomainModule.kt
+++ b/domain/src/main/java/com/hoc/flowmvi/domain/DomainModule.kt
@@ -5,17 +5,18 @@ import com.hoc.flowmvi.domain.usecase.GetUsersUseCase
import com.hoc.flowmvi.domain.usecase.RefreshGetUsersUseCase
import com.hoc.flowmvi.domain.usecase.RemoveUserUseCase
import com.hoc.flowmvi.domain.usecase.SearchUsersUseCase
+import org.koin.core.module.dsl.factoryOf
import org.koin.dsl.module
@JvmField
val domainModule = module {
- factory { GetUsersUseCase(userRepository = get()) }
+ factoryOf(::GetUsersUseCase)
- factory { RefreshGetUsersUseCase(userRepository = get()) }
+ factoryOf(::RefreshGetUsersUseCase)
- factory { RemoveUserUseCase(userRepository = get()) }
+ factoryOf(::RemoveUserUseCase)
- factory { AddUserUseCase(userRepository = get()) }
+ factoryOf(::AddUserUseCase)
- factory { SearchUsersUseCase(userRepository = get()) }
+ factoryOf(::SearchUsersUseCase)
}
diff --git a/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddActivity.kt b/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddActivity.kt
index 5d13b899..eb794d64 100644
--- a/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddActivity.kt
+++ b/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddActivity.kt
@@ -21,13 +21,13 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
-import org.koin.androidx.viewmodel.ext.android.viewModel
+import org.koin.androidx.viewmodel.ext.android.stateViewModel
import timber.log.Timber
@ExperimentalCoroutinesApi
class AddActivity :
AbstractMviActivity(R.layout.activity_add) {
- override val vm by viewModel()
+ override val vm by stateViewModel()
private val addBinding by viewBinding()
override fun onOptionsItemSelected(item: MenuItem): Boolean {
diff --git a/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddModule.kt b/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddModule.kt
index 184ffe8b..d8d5b641 100644
--- a/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddModule.kt
+++ b/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddModule.kt
@@ -2,18 +2,15 @@ package com.hoc.flowmvi.ui.add
import com.hoc.flowmvi.core_ui.navigator.IntentProviders
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import org.koin.androidx.viewmodel.dsl.viewModel
+import org.koin.androidx.viewmodel.dsl.viewModelOf
+import org.koin.core.module.dsl.bind
+import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
@JvmField
@ExperimentalCoroutinesApi
val addModule = module {
- viewModel { params ->
- AddVM(
- addUser = get(),
- savedStateHandle = params.get(),
- )
- }
+ viewModelOf(::AddVM)
- single { AddActivity.IntentProvider() }
+ singleOf(AddActivity::IntentProvider) { bind() }
}
diff --git a/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddVM.kt b/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddVM.kt
index 500695d8..04c43e36 100644
--- a/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddVM.kt
+++ b/feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddVM.kt
@@ -3,6 +3,7 @@ package com.hoc.flowmvi.ui.add
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import arrow.core.orNull
+import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
import com.hoc.flowmvi.domain.model.User
import com.hoc.flowmvi.domain.usecase.AddUserUseCase
import com.hoc.flowmvi.mvi_base.AbstractMviViewModel
@@ -33,7 +34,8 @@ import timber.log.Timber
class AddVM(
private val addUser: AddUserUseCase,
savedStateHandle: SavedStateHandle,
-) : AbstractMviViewModel() {
+ appCoroutineDispatchers: AppCoroutineDispatchers,
+) : AbstractMviViewModel(appCoroutineDispatchers) {
override val viewState: StateFlow
diff --git a/feature-add/src/test/java/com/hoc/flowmvi/ui/add/AddVMTest.kt b/feature-add/src/test/java/com/hoc/flowmvi/ui/add/AddVMTest.kt
index 47d2650c..b5e16cae 100644
--- a/feature-add/src/test/java/com/hoc/flowmvi/ui/add/AddVMTest.kt
+++ b/feature-add/src/test/java/com/hoc/flowmvi/ui/add/AddVMTest.kt
@@ -12,6 +12,7 @@ import com.hoc.flowmvi.domain.usecase.AddUserUseCase
import com.hoc.flowmvi.mvi_testing.BaseMviViewModelTest
import com.hoc.flowmvi.mvi_testing.mapRight
import com.hoc.flowmvi.mvi_testing.returnsWithDelay
+import com.hoc.flowmvi.test_utils.TestAppCoroutineDispatchers
import com.hoc.flowmvi.test_utils.valueOrThrow
import io.mockk.coEvery
import io.mockk.coVerify
@@ -41,7 +42,8 @@ class AddVMTest : BaseMviViewModelTest() {
+ appCoroutineDispatchers: AppCoroutineDispatchers,
+) : AbstractMviViewModel(appCoroutineDispatchers) {
override val viewState: StateFlow
diff --git a/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt b/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt
index e960efb2..20ffb36f 100644
--- a/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt
+++ b/feature-main/src/test/java/com/hoc/flowmvi/ui/main/MainVMTest.kt
@@ -11,6 +11,7 @@ import com.hoc.flowmvi.mvi_testing.BaseMviViewModelTest
import com.hoc.flowmvi.mvi_testing.delayEach
import com.hoc.flowmvi.mvi_testing.mapRight
import com.hoc.flowmvi.mvi_testing.returnsWithDelay
+import com.hoc.flowmvi.test_utils.TestAppCoroutineDispatchers
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.coVerifySequence
@@ -54,6 +55,7 @@ class MainVMTest : BaseMviViewModelTest<
getUsersUseCase = getUserUseCase,
refreshGetUsers = refreshGetUsersUseCase,
removeUser = removeUser,
+ appCoroutineDispatchers = TestAppCoroutineDispatchers(coroutineRule.testDispatcher)
)
}
diff --git a/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchActivity.kt b/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchActivity.kt
index 7579065e..e31d508b 100644
--- a/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchActivity.kt
+++ b/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchActivity.kt
@@ -30,7 +30,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
-import org.koin.androidx.viewmodel.ext.android.viewModel
+import org.koin.androidx.viewmodel.ext.android.stateViewModel
import timber.log.Timber
import kotlin.time.ExperimentalTime
@@ -40,7 +40,7 @@ import kotlin.time.ExperimentalTime
class SearchActivity :
AbstractMviActivity(R.layout.activity_search) {
private val binding by viewBinding()
- override val vm by viewModel()
+ override val vm by stateViewModel()
private val searchViewQueryTextEventChannel = Channel()
private val searchAdapter = SearchAdapter()
diff --git a/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchModule.kt b/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchModule.kt
index e52baf28..a7195932 100644
--- a/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchModule.kt
+++ b/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchModule.kt
@@ -3,7 +3,9 @@ package com.hoc.flowmvi.ui.search
import com.hoc.flowmvi.core_ui.navigator.IntentProviders
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
-import org.koin.androidx.viewmodel.dsl.viewModel
+import org.koin.androidx.viewmodel.dsl.viewModelOf
+import org.koin.core.module.dsl.bind
+import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
import kotlin.time.ExperimentalTime
@@ -12,12 +14,7 @@ import kotlin.time.ExperimentalTime
@FlowPreview
@ExperimentalTime
val searchModule = module {
- single { SearchActivity.IntentProvider() }
+ singleOf(SearchActivity::IntentProvider) { bind() }
- viewModel { params ->
- SearchVM(
- searchUsersUseCase = get(),
- savedStateHandle = params.get(),
- )
- }
+ viewModelOf(::SearchVM)
}
diff --git a/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchVM.kt b/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchVM.kt
index df9b2526..f234f1ba 100644
--- a/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchVM.kt
+++ b/feature-search/src/main/java/com/hoc/flowmvi/ui/search/SearchVM.kt
@@ -2,6 +2,7 @@ package com.hoc.flowmvi.ui.search
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
+import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
import com.hoc.flowmvi.domain.usecase.SearchUsersUseCase
import com.hoc.flowmvi.mvi_base.AbstractMviViewModel
import com.hoc081098.flowext.flatMapFirst
@@ -36,7 +37,8 @@ import kotlin.time.ExperimentalTime
class SearchVM(
private val searchUsersUseCase: SearchUsersUseCase,
private val savedStateHandle: SavedStateHandle,
-) : AbstractMviViewModel() {
+ appCoroutineDispatchers: AppCoroutineDispatchers,
+) : AbstractMviViewModel(appCoroutineDispatchers) {
override val viewState: StateFlow
diff --git a/feature-search/src/test/java/com/hoc/flowmvi/ui/search/SearchVMTest.kt b/feature-search/src/test/java/com/hoc/flowmvi/ui/search/SearchVMTest.kt
index 782ecc4e..da9514bf 100644
--- a/feature-search/src/test/java/com/hoc/flowmvi/ui/search/SearchVMTest.kt
+++ b/feature-search/src/test/java/com/hoc/flowmvi/ui/search/SearchVMTest.kt
@@ -9,6 +9,7 @@ import com.hoc.flowmvi.mvi_testing.BaseMviViewModelTest
import com.hoc.flowmvi.mvi_testing.mapRight
import com.hoc.flowmvi.mvi_testing.returnsManyWithDelay
import com.hoc.flowmvi.mvi_testing.returnsWithDelay
+import com.hoc.flowmvi.test_utils.TestAppCoroutineDispatchers
import com.hoc.flowmvi.ui.search.SearchVM.Companion.SEARCH_DEBOUNCE_DURATION
import com.hoc081098.flowext.concatWith
import com.hoc081098.flowext.timer
@@ -44,7 +45,8 @@ class SearchVMTest : BaseMviViewModelTest :
+abstract class AbstractMviViewModel(
+ private val appCoroutineDispatchers: AppCoroutineDispatchers,
+) :
MviViewModel, ViewModel() {
- protected val logTag by lazy(LazyThreadSafetyMode.PUBLICATION) {
+ protected val logTag by lazy(PUBLICATION) {
this::class.java.simpleName.let { tag: String ->
// Tag length limit was removed in API 26.
if (tag.length <= MAX_TAG_LENGTH || Build.VERSION.SDK_INT >= 26) {
@@ -43,7 +50,14 @@ abstract class AbstractMviViewModel get() = intentMutableFlow
// Extensions on Flow using viewModelScope.
diff --git a/test-utils/src/main/java/com/hoc/flowmvi/test_utils/TestAppCoroutineDispatchers.kt b/test-utils/src/main/java/com/hoc/flowmvi/test_utils/TestAppCoroutineDispatchers.kt
new file mode 100644
index 00000000..46ee75bf
--- /dev/null
+++ b/test-utils/src/main/java/com/hoc/flowmvi/test_utils/TestAppCoroutineDispatchers.kt
@@ -0,0 +1,13 @@
+package com.hoc.flowmvi.test_utils
+
+import com.hoc.flowmvi.core.dispatchers.AppCoroutineDispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestDispatcher
+
+@ExperimentalCoroutinesApi
+class TestAppCoroutineDispatchers(private val testCoroutineDispatcher: TestDispatcher) :
+ AppCoroutineDispatchers {
+ override val main get() = testCoroutineDispatcher
+ override val mainImmediate get() = testCoroutineDispatcher
+ override val io get() = testCoroutineDispatcher
+}
diff --git a/test-utils/src/main/java/com/hoc/flowmvi/test_utils/TestDispatchers.kt b/test-utils/src/main/java/com/hoc/flowmvi/test_utils/TestDispatchers.kt
deleted file mode 100644
index c5fb3d7e..00000000
--- a/test-utils/src/main/java/com/hoc/flowmvi/test_utils/TestDispatchers.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.hoc.flowmvi.test_utils
-
-import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestDispatcher
-
-@ExperimentalCoroutinesApi
-class TestDispatchers(testCoroutineDispatcher: TestDispatcher) :
- CoroutineDispatchers {
- override val main: CoroutineDispatcher = testCoroutineDispatcher
- override val io: CoroutineDispatcher = testCoroutineDispatcher
-}