DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Kotlin sealed interface — Type-Safe State, Events & Navigation

Kotlin sealed interface — Type-Safe State, Events & Navigation

Sealed classes and sealed interfaces are powerful Kotlin features that ensure type-safe hierarchies. Let's explore how they solve real Android patterns.

sealed class vs sealed interface

sealed class restricts inheritance in the same package. sealed interface (Kotlin 1.6+) adds multi-inheritance:

sealed interface UiState
sealed class DataState : UiState

data class Loading : DataState()
data class Success(val data: String) : DataState()
data class Error(val exception: Exception) : DataState()

// Multiple inheritance
class CachedState(val cached: String) : DataState(), Serializable
Enter fullscreen mode Exit fullscreen mode

UI State Pattern

Use sealed classes for exhaustive when expressions:

sealed class ScreenState {
    object Loading : ScreenState()
    data class Content(val items: List<String>) : ScreenState()
    data class Error(val message: String) : ScreenState()
    object Empty : ScreenState()
}

fun render(state: ScreenState) {
    when (state) {
        is ScreenState.Loading -> showSpinner()
        is ScreenState.Content -> showList(state.items)
        is ScreenState.Error -> showError(state.message)
        is ScreenState.Empty -> showEmpty()
        // Compiler ensures all cases covered
    }
}
Enter fullscreen mode Exit fullscreen mode

User Action sealed interface Pattern

sealed interface UserAction {
    data class Search(val query: String) : UserAction
    data class Select(val id: Int) : UserAction
    object Refresh : UserAction
    data class Delete(val id: Int) : UserAction
}

class ViewModel : ViewModel() {
    fun onAction(action: UserAction) {
        when (action) {
            is UserAction.Search -> search(action.query)
            is UserAction.Select -> select(action.id)
            UserAction.Refresh -> refresh()
            is UserAction.Delete -> delete(action.id)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Navigation Routes with property

sealed class Route(val path: String) {
    object Home : Route("home")
    data class Details(val id: Int) : Route("details/$id")
    object Settings : Route("settings")
}

fun navigate(route: Route) {
    navController.navigate(route.path)
}
Enter fullscreen mode Exit fullscreen mode

Error handling sealed hierarchy

sealed class AppError(val message: String) {
    class NetworkError(msg: String = "No internet") : AppError(msg)
    class ServerError(val code: Int, msg: String) : AppError(msg)
    class AuthError(msg: String = "Unauthorized") : AppError(msg)
    class UnknownError(val throwable: Throwable) : AppError(throwable.message ?: "Unknown")
}

fun Throwable.toAppError(): AppError = when (this) {
    is IOException -> AppError.NetworkError()
    is HttpException -> AppError.ServerError(code, message ?: "")
    is SecurityException -> AppError.AuthError()
    else -> AppError.UnknownError(this)
}
Enter fullscreen mode Exit fullscreen mode

Sealed types prevent runtime surprises and enable compile-time safety for Android patterns.

8 Android app templates: https://myougatheax.gumroad.com

Top comments (0)