Skip to content

Instantly share code, notes, and snippets.

@adityabhaskar
Last active November 17, 2025 15:38
Show Gist options
  • Select an option

  • Save adityabhaskar/8dc39f4593a60c363a798d326020d6c6 to your computer and use it in GitHub Desktop.

Select an option

Save adityabhaskar/8dc39f4593a60c363a798d326020d6c6 to your computer and use it in GitHub Desktop.
Demo of simplistic preferences builder dsl
@Target(AnnotationTarget.TYPE)
@DslMarker
annotation class PreferenceDsl
@DslMarker
annotation class PreferenceBuilderDsl
@PreferenceBuilderDsl
interface BaseBuilder<out T> {
fun build(): T
}
import androidx.annotation.StringRes
data class PreferenceScreen(
@param:StringRes val titleRes: Int,
val sections: List<PreferenceSection>,
) {
class Builder: BaseBuilder<PreferenceScreen> {
var titleRes: Int? = null
var sections: MutableList<PreferenceSection> = mutableListOf()
override fun build(): PreferenceScreen {
return PreferenceScreen(
titleRes = titleRes ?: error("title is required"),
sections = sections.toList(),
)
}
}
}
fun preferenceScreen(init: @PreferenceDsl PreferenceScreen.Builder.() -> Unit): PreferenceScreen {
return PreferenceScreen.Builder().apply(init).build()
}
import androidx.annotation.StringRes
sealed interface Preference
data class PreferenceSection(
@param:StringRes val titleRes: Int,
@param:StringRes val descriptionRes: Int?,
val preferences: List<Preference>
) {
class Builder : BaseBuilder<PreferenceSection> {
var titleRes: Int? = null
var descriptionRes: Int? = null
val preferences = mutableListOf<Preference>()
override fun build() = PreferenceSection(
titleRes = titleRes ?: error("Title resource not set"),
descriptionRes = descriptionRes ?: error("Description resource not set"),
preferences = preferences.toList(),
)
}
}
fun PreferenceScreen.Builder.preferenceSection(block: @PreferenceDsl PreferenceSection.Builder.() -> Unit) {
sections.add(PreferenceSection.Builder().apply(block).build())
}
val rootPreferenceScreen = preferenceScreen {
titleRes = 12345
preferenceSection {
titleRes = 12345
switchPreference {
titleRes = 12345
key = "12345"
}
switchPreference {
titleRes = 12345
key = "12345"
}
switchPreference {
titleRes = 12345
key = "12345"
}
}
someSubSection()
}
fun PreferenceScreen.Builder.someSubSection() = preferenceSection {
titleRes = 12345
switchPreference {
titleRes = 12345
key = "12345"
}
switchPreference {
titleRes = 12345
key = "12345"
}
switchPreference {
titleRes = 12345
key = "12345"
}
}
import androidx.annotation.StringRes
data class SwitchPreference(
@param:StringRes val titleRes: Int,
@param:StringRes val summaryRes: Int?,
val key: String,
val enabled: Boolean = true,
) : Preference {
internal class Builder : BaseBuilder<SwitchPreference> {
var titleRes: Int? = null
var summaryRes: Int? = null
var key: String = ""
var enabled: Boolean = true
override fun build(): SwitchPreference {
require(key.isNotBlank()) { "key must be set" }
return SwitchPreference(
titleRes = titleRes ?: error("title must be set"),
summaryRes = summaryRes,
key = key,
enabled = enabled,
)
}
}
}
internal fun PreferenceSection.Builder.switchPreference(init: @PreferenceDsl SwitchPreference.Builder.() -> Unit) {
preferences.add(SwitchPreference.Builder().apply(init).build())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment