I'm trying to read a list of objects from the database and mapping it to another type of list.
// Returns either a Failure or the expected result
suspend fun getCountries(): Either<Failure, List<CountryItem>> {
// Get the result from the database
val result = countryLocalDataSource.getCountries()
// Left means Failure
if (result.isLeft) {
// Retrieve the error from the database
lateinit var error: Failure
result.either({
error = it
}, {})
// Return the result
return Either.Left(error)
}
// The database returns a List of Country objects, we need to map it to another object (CountryItem)
val countryItems: MutableList<CountryItem> = mutableListOf()
// Iterate the Country List and construct a new List of CountryItems
result.map { countries -> {
countries.forEach {
// Assign some values from an Enum (localized string resources)
val countryEnumValue = Countries.fromId(it.id)
countryEnumValue?.let { countryIt ->
val countryStringNameRes = countryIt.nameStringRes;
// Create the new CountryItem object (@StringRes value: Int, isSelected: Bool)
countryItems.add(CountryItem(countryStringNameRes, false))
}
}
} }
// Because this is a success, return as Right with the newly created List of CountryItems
return Either.Right(countryItems)
}
For the sake of readability I didn't included the whole Repository
or the DAO
classes and I have left comments in the code snippet above.
In a nutshell: I'm using Kotlin's Coroutines for accessing the database in a separated thread and I'm handling the response on the UI Thread
. Using the Either class in order to return two different results (failure or success).
The above code works, however It's too ugly. Is this the right approach to deliver the result?
What I'm trying to do is to refactor the code above.
The whole problem is caused by the two different object types. The Database Data Source API
is returning an Either<Failure, List<Country>>
, meanwhile the function is expected to return an Either<Failure, List<CountryItem>>
.
I can't deliver a List<CountryItem>
directly from the Database Data Source API
, because Android Studio doesn't let me compile the project (entities implementing interfaces, compile error, etc.). What I'm trying to achieve is to map the Either
result in a nicer way.
Try using Kotlin's Result
So in your case you can write something like:
return result.mapCatching { list: List<Country> -> /*return here List<CountryItem>>*/ }
And for checking result call:
result.fold(
onSuccess = {...},
onFailure = {...}
)
In order to invoke a constructor you should call Result.success(T)
or Result.failure(Throwable)
Unfortunately, you'll also need to suppress use-as-return-type warnings How to
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With