Migration Guide — Android (5.x to 6.x)
Version 6.x is a major release focused on modern Android development with Jetpack Compose and Kotlin Coroutines.
Toolchain Requirements
Upgrade your project to meet the minimum requirements:
| Tool | Required version |
|---|---|
| Android Gradle Plugin | 9.1 |
| Gradle | 9.4 |
| Kotlin | 2.4 |
| JDK | 17 |
compileSdk / targetSdk |
36 |
minSdk |
23 |
Remove multidex (not needed with minSdk ≥ 21) and remove Jetifier (android.enableJetifier) from gradle.properties — Arkitekt is AndroidX-only.
Hilt + Kotlin 2.4
Hilt currently bundles an older kotlin-metadata-jvm that may fail to parse Kotlin 2.4 metadata (google/dagger#5001). If you hit a metadata parsing error during the KSP/Hilt build, add the matching version as a KSP dependency so the highest version on the processor classpath wins:
dependencies {
ksp("org.jetbrains.kotlin:kotlin-metadata-jvm:2.4.0")
}
This is a temporary workaround until Hilt updates its bundled version.
Removed Modules
| Module | Replacement |
|---|---|
rx-usecases, rx-usecases-test |
cr-usecases (Coroutines) |
dagger |
Dagger-Hilt (@HiltViewModel, @AndroidEntryPoint) |
bindingadapters |
Jetpack Compose |
example-minimal, example-hilt |
Consolidated example module |
Removed Classes
ViewModel Base Classes
| Removed | Replacement |
|---|---|
BaseViewModel (from core) |
BaseCoreViewModel (core) or BaseViewModel (compose) |
BaseCrViewModel (from cr-usecases) |
BaseViewModel (compose) |
Fragment / Activity Base Classes
| Removed | Replacement |
|---|---|
ViewModelActivity, BindingViewModelActivity |
ComponentActivity with @AndroidEntryPoint |
ViewModelFragment, BindingViewModelFragment |
Compose navigation |
ViewModelBottomSheetDialogFragment, BindingViewModelBottomSheetDialogFragment |
Compose bottom sheets |
ViewModelDialogFragment, BindingViewModelDialogFragment |
Compose dialogs |
Dagger Classes
| Removed | Replacement |
|---|---|
BaseViewModelFactory, BaseSavedStateViewModelFactory |
@HiltViewModel with hiltViewModel() |
BaseDaggerActivity, BaseDaggerFragment and Binding variants |
@AndroidEntryPoint |
ViewModelCreator, ViewModelFactory |
No longer needed with Hilt |
LiveData Components
| Removed | Replacement |
|---|---|
LiveEvent, LiveEventBus |
Event with Channel-based events |
DefaultValueLiveData, DefaultValueMediatorLiveData |
StateFlow or Compose State |
NonNullLiveData |
StateFlow or Compose State |
UiData, UiDataExtensions, UiDataMediator |
StateFlow or Compose State |
LiveDataExtensions, LiveDataUtils |
Kotlin Flow operators |
DataBinding
All DataBinding support has been removed. Use Jetpack Compose instead.
UseCase API Changes
UseCase is now an interface
UseCase<ARGS, T> changed from an abstract class to an interface. Update all definitions:
// Before
class LoginUseCase : UseCase<LoginData, User>() { ... }
// After
class LoginUseCase : UseCase<LoginData, User> { ... }
The deferred property that tracked cancellation has been removed — cancellation is now managed internally via CoroutineScopeOwner.useCaseJobPool.
FlowUseCase is now an interface
Same change applies to FlowUseCase:
// Before
class ObserveUserUseCase : FlowUseCase<Unit, User>() { ... }
// After
class ObserveUserUseCase : FlowUseCase<Unit, User> { ... }
The job property has been removed. The running job is stored in useCaseJobPool.
executeMapped removed
executeMapped has been removed from FlowUseCase. Apply transformations inside build() instead:
// Before
flowUseCase.executeMapped(Unit, transform = { it.name }) {
onNext { name -> /* ... */ }
}
// After
class ObserveUserNamesUseCase : FlowUseCase<Unit, String> {
override fun build(args: Unit): Flow<String> =
userStore.observeUsers().map { it.name }
}
execute uses context parameters
The execute extensions are now declared with Kotlin context parameters. Context parameters are stable as of Kotlin 2.4, so no compiler flag is needed — call execute(...) directly from inside any CoroutineScopeOwner (e.g. a ViewModel or Component) and the receiver is resolved automatically. The call sites remain syntactically the same as before:
loginUseCase.execute(args) { onSuccess { /* ... */ } }
CoroutineScopeOwner Changes
coroutineScope renamed to useCaseScope
The coroutineScope property on CoroutineScopeOwner has been renamed to useCaseScope. Update any custom CoroutineScopeOwner implementations:
// Before
override val coroutineScope: CoroutineScope = viewModelScope
// After
override val useCaseScope: CoroutineScope = viewModelScope
useCaseJobPool is now required
Custom CoroutineScopeOwner implementations must also provide useCaseJobPool:
override val useCaseJobPool: MutableMap<Any, Job> = mutableMapOf()
BaseViewModel and BaseCoreViewModel from Arkitekt already provide both — only custom implementations need to be updated.
Result Type Migration
Arkitekt's custom Result<VALUE> sealed class has been removed. The sync-execute variant now returns kotlin.Result<T>.
Replacing extension functions
| Old (Arkitekt Result) | New (kotlin.Result) |
|---|---|
.getOrNull() |
.getOrNull() ✓ built-in |
.getOrDefault(v) |
.getOrDefault(v) ✓ built-in |
.getOrElse { } |
.getOrElse { } ✓ built-in |
.getOrThrow() |
.getOrThrow() ✓ built-in |
.getOrCancel { } |
.getOrCancel { } from cr-usecases |
.map { } |
.map { } ✓ built-in |
.fold(onSuccess, onError) |
.fold(onSuccess, onFailure) ✓ built-in |
tryCatch { } |
runCatching { } ✓ built-in |
Destructuring
kotlin.Result does not support destructuring declarations. Replace any val (value, error) = result calls with explicit getOrNull() / exceptionOrNull() calls.
Migration Path
- Upgrade toolchain to AGP 9.1, Gradle 9.4, Kotlin 2.4, JDK 17
- Remove multidex and Jetifier from
gradle.properties - Add
ksp("org.jetbrains.kotlin:kotlin-metadata-jvm:2.4.0")if you hit Hilt metadata parsing errors (google/dagger#5001) - Replace Fragment/Activity base classes with
ComponentActivity+@AndroidEntryPoint - Replace LiveData with
StateFlowor ComposeState - Replace
LiveEventwith Channel-basedEventsystem - Migrate UI to Jetpack Compose
- Replace old
BaseViewModelwithBaseCoreViewModelorBaseViewModel - Replace Dagger 2 with Dagger-Hilt
- Update UseCase/FlowUseCase from abstract class to interface (remove
()from supertype) - Remove
executeMappedcalls — apply mapping inbuild()instead - Rename
coroutineScope→useCaseScopein customCoroutineScopeOwnerimplementations; adduseCaseJobPool - Replace custom
Resultusage withkotlin.Resultextensions