Resource
Resource
is a sealed class
that allows you to wrap any object based on a state. It has these options:
-
๐ Loading: To use at that moment that a loading indicator should appear. -
๐ Success: When the happy path occurs. -
โ Error: If there is a problem you will get this.
This library works very well when used in conjunction with NetworkResponse
which is very similar to Resource
but is intended for use with Retrofit
.
For more information see the website
Download
This library is Kotlin Multiplatform but at this moment jvm
is the only artifact generated. It is available at Maven Central.
implementation("com.javiersc.resource:resource:$version")
Fold your Resource
Fold a Resource
invokes multiple callbacks to manage its state for any event. A normal flow can be:
- Emit
Loading
to show the progress indicator. - Emit
Success
to populate your data or emitError
if something were wrong to show an error.
val dog: Dog = Dog("Auri")
val resource: Resource<Dog, Error> = Resource.Success(dog)
resource.folder {
loading { println("Loading: Yes") }
noLoading { println("Loading: no") } // Invoked
success { dog: Dog -> println("Success: $dog") } // Invoked
noSuccess { println("Success: no") }
error { error: Error -> println("Error: $error") }
noError { println("Error: no") } // Invoked
}
Exists a fold
function similar to folder buth without the builder pattern
val dog: Dog = Dog("Auri")
val resource: Resource<Dog, Error> = Resource.Success(dog)
resource.fold(
loading = { println("Loading: Yes") },
noLoading = { println("Loading: no") }, // Invoked
success = { dog: Dog -> println("Success: $dog") }, // Invoked
noSuccess = { println("Success: no") },
error = { error: Error -> println("Error: $error") },
noError = { println("Error: no") }, // Invoked
)
You don't have to add all those functions, for example, you usually only have to use:
loading
to show a progress indicator.noLoading
to hide the progress indicator.success
to load the data.error
to show and error.
Mappers and common extension functions
Map a Resource
to another Resource
is possible with the following extension function:
Resource
toResource
val anotherResource: Resource<AnotherUser, AnotherError> = resource.map(
success = { user: User -> user.toAnotherUser() },
error = { error: Error -> error.toAnotherError() }
)
// toAnotherUser() and toAnotherError() mappers should be created by yourself, if they are
// extension functions and the resource uses inference for the type:
val anotherResource = resource.map(User::toAnotherUser, Error::toAnotherError)
- Some value to
Resource
val name: String = "Auri"
val nameResource = name.toResourceSuccess()
val message: String = "Some error message"
val messageResource = message.toResourceError()
- A lot of checkers for each state, for example:
val resource: Resource<String> = Resource.Success("Auri")
resource.ifSuccess { data: String ->
println(data) // "Auri"
}
You can see all the common extension functions here and here
Flow
There are four Flow
extension functions:
Flow<R>.map(...)
included in Kotlin, let you to easily map the object inside yourFlow
to anyResource
:
val usersFlow: Flow<List<User>>
val usersResourceFlow: Flow<Resource<List<User>, Error>> =
usersFlow.map { users: List<User> -> Resource.Success(users) }
Flow<R>.toResourceSuccess()
val usersSuccessFlow: Flow<Resource<List<User>, Error>> = usersFlow.toResourceSuccess()
Flow<R>.toResourceError()
val usersErrorFlow: Flow<Resource<List<User>, Error>> = usersFlow.toResourceError()