Skip to main content

MaestroLoadableResult

Overview

MaestroLoadableResult is a sealed interface that represents the state of an asynchronous operation in the Maestro SDK. It follows a common pattern for handling loading states, success results, and error conditions in a type-safe manner.

Syntax

sealed interface MaestroLoadableResult<out T : Any>

Type Parameters

ParameterDescription
TThe type of data contained in a successful result. Must be a non-null type extending Any.

Sealed Subclasses

Success

Represents a successful operation with data.

data class Success<T : Any>(
val data: T
) : MaestroLoadableResult<T>

Properties:

  • data: T - The successfully loaded data

Error

Represents a failed operation with error information.

data class Error(
val source: MaestroNetworkError
) : MaestroLoadableResult<Nothing>

Properties:

  • source: MaestroNetworkError - Information about the error that occurred

Loading

Represents an operation that is currently in progress.

data object Loading : MaestroLoadableResult<Nothing>

Usage Example

Basic Pattern Matching

fun handleResult(result: MaestroLoadableResult<UserData>) {
when (result) {
is MaestroLoadableResult.Loading -> {
// Show loading indicator
showLoadingSpinner()
}
is MaestroLoadableResult.Success -> {
// Handle successful data
val userData = result.data
displayUserData(userData)
}
is MaestroLoadableResult.Error -> {
// Handle error
val error = result.source
showErrorMessage(error.message)
}
}
}

With Key Plays Data

override fun keyPlaysData(): MaestroLoadableResult<KeyPlaysData> {
return if (isLoading) {
MaestroLoadableResult.Loading
} else if (keyPlaysDataAvailable) {
MaestroLoadableResult.Success(currentKeyPlaysData)
} else {
MaestroLoadableResult.Error(
MaestroNetworkError(message = "Failed to load key plays")
)
}
}

Reactive UI Updates

class MyViewModel : ViewModel() {
private val _dataState = MutableStateFlow<MaestroLoadableResult<MyData>>(
MaestroLoadableResult.Loading
)
val dataState: StateFlow<MaestroLoadableResult<MyData>> = _dataState

fun loadData() {
_dataState.value = MaestroLoadableResult.Loading

viewModelScope.launch {
try {
val data = repository.fetchData()
_dataState.value = MaestroLoadableResult.Success(data)
} catch (e: Exception) {
_dataState.value = MaestroLoadableResult.Error(
MaestroNetworkError(message = e.message ?: "Unknown error")
)
}
}
}
}

Helper Extension Functions

// Extension to check if result is successful
fun <T : Any> MaestroLoadableResult<T>.isSuccess(): Boolean {
return this is MaestroLoadableResult.Success
}

// Extension to get data or null
fun <T : Any> MaestroLoadableResult<T>.getOrNull(): T? {
return (this as? MaestroLoadableResult.Success)?.data
}

// Extension to map success data
fun <T : Any, R : Any> MaestroLoadableResult<T>.map(
transform: (T) -> R
): MaestroLoadableResult<R> {
return when (this) {
is MaestroLoadableResult.Success -> MaestroLoadableResult.Success(transform(data))
is MaestroLoadableResult.Error -> this
is MaestroLoadableResult.Loading -> MaestroLoadableResult.Loading
}
}

Common Patterns

Loading State Management

class DataManager {
private var state: MaestroLoadableResult<Data> = MaestroLoadableResult.Loading

fun getData(): MaestroLoadableResult<Data> = state

suspend fun refreshData() {
state = MaestroLoadableResult.Loading

state = try {
val newData = fetchFromNetwork()
MaestroLoadableResult.Success(newData)
} catch (e: Exception) {
MaestroLoadableResult.Error(
MaestroNetworkError(message = e.localizedMessage)
)
}
}
}

Composable UI (Jetpack Compose)

@Composable
fun DataScreen(result: MaestroLoadableResult<MyData>) {
when (result) {
is MaestroLoadableResult.Loading -> {
CircularProgressIndicator()
}
is MaestroLoadableResult.Success -> {
DataContent(data = result.data)
}
is MaestroLoadableResult.Error -> {
ErrorView(error = result.source)
}
}
}

Benefits

  • Type Safety: Compile-time guarantee that all states are handled
  • Exhaustive When: Kotlin ensures all sealed class cases are covered
  • Clear State Representation: Explicitly models loading, success, and error states
  • Null Safety: Eliminates null checks by using proper types
  • Composability: Easy to combine and transform results

See Also