I want to create an Enum or Sealed class that is gonna hold the values for a DropDownMenu in order to sort a list.
In my ViewModel I have
result.data.map { it.toPresentationModel() }.sortedWith(compareBy {it.date})
Instead of compareBy {it.date})
I wanna do that inside the enum/sealed class because for other options I wanna do (compareByDescending{it.date})
and just pass here the current selected value of the DropDownMenu.
And inside compareBy() I need to pass a parameter from a Data class
And also I would like to retrieve the enum's value name to put it inside my DropDownMenu
Here's how it looks like
Is this possible? Any suggestions please?
CodePudding user response:
You can implement functions inside of enums:
enum class SortBy(val name: String) {
DATE("Date") {
override fun <T : Comparable> sort(data: List<T>): List<T> { ... }
},
TIME("Time") {
override fun <T : Comparable> sort(data: List<T>): List<T> { ... }
},
AMOUNT("Amount") {
override fun <T : Comparable> sort(data: List<T>): List<T> { ... }
},
PRICE("Price") {
override fun <T : Comparable> sort(data: List<T>): List<T> { ... }
};
abstract fun <T : Comparable> sort(data: List<T>): List<T>
}
Notice the semicolon after the last constant.
You can then implement it as an adapter or something.
CodePudding user response:
Your enum class can itself implement the Comparator interface so you can directly pass its instances to compareBy
and other similar functions.
I don't think you should hard-code the names of the values, because it will make translations difficult. Put those names in String resources. You can perform a one-time initialization of the names once you have a Context available. You can override toString()
to present this possibly translated name to make it easy to use this enum in drop-downs.
For example, given this class:
data class PresentationModel(val date: LocalDate, val price: BigInteger)
You could create this enum:
enum class PresentationSort(
private val nameId: Int,
compareBy: (PresentationModel)->Comparable<*>
): Comparator<PresentationModel> {
Date(R.string.date, PresentationModel::date),
Price(R.string.price, PresentationModel::price);
private var resourceName: String? = null
private val comparator = compareBy(compareBy)
override fun compare(o1: PresentationModel?, o2: PresentationModel?): Int
= comparator.compare(o1, o2)
override fun toString() = resourceName ?: name
companion object {
fun initialize(context: Context) {
for (value in values()) resourceName = context.getString(value.nameId)
}
}
}
And pass it like:
result.data.map { it.toPresentationModel() }.sortedWith(PresentationSort.Date)
PresentationSort.initialize()
should be called at the earliest opportunity, like at the beginning of onCreate()
of the MainActivity. This will also cause it to update to the latest translation if the user changed languages while your app is open.