From 388af789948cc7409589e5853dea0b3f14ea239b Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 17 Feb 2020 23:38:10 -0800 Subject: Create new kpref model --- .idea/codeStyles/codeStyleConfig.xml | 1 + .../main/kotlin/ca/allanwang/kau/kpref/KPref.kt | 35 ++---- .../kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt | 132 ++++++++++++++++++--- .../kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt | 12 +- .../kotlin/ca/allanwang/kau/kpref/KPrefFactory.kt | 22 ++++ .../ca/allanwang/kau/kpref/KPrefSingleDelegate.kt | 14 ++- 6 files changed, 162 insertions(+), 54 deletions(-) create mode 100644 core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefFactory.kt diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index a55e7a1..6e6eec1 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,6 @@ + \ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt index fc7a76a..2f8a6aa 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt @@ -15,10 +15,7 @@ */ package ca.allanwang.kau.kpref -import android.content.Context -import android.content.SharedPreferences import ca.allanwang.kau.kotlin.ILazyResettable -import ca.allanwang.kau.logging.KL /** * Created by Allan Wang on 2017-06-07. @@ -32,30 +29,16 @@ import ca.allanwang.kau.logging.KL * Furthermore, all kprefs are held in the [prefMap], * so if you wish to reset a preference, you must also invalidate the kpref * from that map - * - * You may optionally override [deleteKeys]. This will be called on initialization - * And delete all keys returned from that method */ -open class KPref(builder: KPrefBuilder = KPrefBuilderAndroid) : KPrefBuilder by builder { - - lateinit var PREFERENCE_NAME: String - lateinit var sp: SharedPreferences +open class KPref private constructor( + val preferenceName: String, + val builder: KPrefBuilder +) : KPrefBuilder by builder { - fun initialize( - c: Context, - preferenceName: String, - sharedPrefs: SharedPreferences = c.applicationContext.getSharedPreferences(preferenceName, Context.MODE_PRIVATE) - ) { - PREFERENCE_NAME = preferenceName - sp = sharedPrefs - KL.d { "Shared Preference $preferenceName has been initialized" } - val toDelete = deleteKeys() - if (toDelete.isNotEmpty()) { - val edit = sp.edit() - toDelete.forEach { edit.remove(it) } - edit.apply() - } - } + constructor(preferenceName: String, factory: KPrefFactory) : this( + preferenceName, + factory.createBuilder(preferenceName) + ) internal val prefMap: MutableMap> = mutableMapOf() @@ -64,6 +47,4 @@ open class KPref(builder: KPrefBuilder = KPrefBuilderAndroid) : KPrefBuilder by } operator fun get(key: String): ILazyResettable<*>? = prefMap[key] - - open fun deleteKeys(): Array = arrayOf() } diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt index 8f6d0c5..b8fb8ea 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt @@ -15,22 +15,44 @@ */ package ca.allanwang.kau.kpref +import android.content.SharedPreferences + interface KPrefBuilder { - fun KPref.kpref(key: String, fallback: Boolean, postSetter: (value: Boolean) -> Unit = {}): KPrefDelegate + fun KPref.kpref( + key: String, + fallback: Boolean, + postSetter: (value: Boolean) -> Unit = {} + ): KPrefDelegate - fun KPref.kpref(key: String, fallback: Float, postSetter: (value: Float) -> Unit = {}): KPrefDelegate + fun KPref.kpref( + key: String, + fallback: Float, + postSetter: (value: Float) -> Unit = {} + ): KPrefDelegate @Deprecated( "Double is not supported in SharedPreferences; cast to float yourself", ReplaceWith("kpref(key, fallback.toFloat(), postSetter)"), DeprecationLevel.WARNING ) - fun KPref.kpref(key: String, fallback: Double, postSetter: (value: Float) -> Unit = {}): KPrefDelegate = + fun KPref.kpref( + key: String, + fallback: Double, + postSetter: (value: Float) -> Unit = {} + ): KPrefDelegate = kpref(key, fallback.toFloat(), postSetter) - fun KPref.kpref(key: String, fallback: Int, postSetter: (value: Int) -> Unit = {}): KPrefDelegate + fun KPref.kpref( + key: String, + fallback: Int, + postSetter: (value: Int) -> Unit = {} + ): KPrefDelegate - fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit = {}): KPrefDelegate + fun KPref.kpref( + key: String, + fallback: Long, + postSetter: (value: Long) -> Unit = {} + ): KPrefDelegate fun KPref.kpref( key: String, @@ -38,32 +60,97 @@ interface KPrefBuilder { postSetter: (value: Set) -> Unit = {} ): KPrefDelegate> - fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit = {}): KPrefDelegate + fun KPref.kpref( + key: String, + fallback: String, + postSetter: (value: String) -> Unit = {} + ): KPrefDelegate fun KPref.kprefSingle(key: String): KPrefSingleDelegate + + /** + * Remove keys from pref so they revert to the default + */ + fun KPref.deleteKeys(keys: Array) } -object KPrefBuilderAndroid : KPrefBuilder { +class KPrefBuilderAndroid(val sp: SharedPreferences) : KPrefBuilder { override fun KPref.kpref(key: String, fallback: Boolean, postSetter: (value: Boolean) -> Unit) = - KPrefDelegateAndroid(key, fallback, this, KPrefBooleanTransaction, postSetter) + KPrefDelegateAndroid( + key, + fallback, + this, + this@KPrefBuilderAndroid, + KPrefBooleanTransaction, + postSetter + ) override fun KPref.kpref(key: String, fallback: Float, postSetter: (value: Float) -> Unit) = - KPrefDelegateAndroid(key, fallback, this, KPrefFloatTransaction, postSetter) + KPrefDelegateAndroid( + key, + fallback, + this, + this@KPrefBuilderAndroid, + KPrefFloatTransaction, + postSetter + ) override fun KPref.kpref(key: String, fallback: Int, postSetter: (value: Int) -> Unit) = - KPrefDelegateAndroid(key, fallback, this, KPrefIntTransaction, postSetter) + KPrefDelegateAndroid( + key, + fallback, + this, + this@KPrefBuilderAndroid, + KPrefIntTransaction, + postSetter + ) override fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit) = - KPrefDelegateAndroid(key, fallback, this, KPrefLongTransaction, postSetter) - - override fun KPref.kpref(key: String, fallback: Set, postSetter: (value: Set) -> Unit) = - KPrefDelegateAndroid(key, fallback, this, KPrefSetTransaction, postSetter) + KPrefDelegateAndroid( + key, + fallback, + this, + this@KPrefBuilderAndroid, + KPrefLongTransaction, + postSetter + ) + + override fun KPref.kpref( + key: String, + fallback: Set, + postSetter: (value: Set) -> Unit + ) = + KPrefDelegateAndroid( + key, + fallback, + this, + this@KPrefBuilderAndroid, + KPrefSetTransaction, + postSetter + ) override fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit) = - KPrefDelegateAndroid(key, fallback, this, KPrefStringTransaction, postSetter) - - override fun KPref.kprefSingle(key: String) = KPrefSingleDelegateAndroid(key, this) + KPrefDelegateAndroid( + key, + fallback, + this, + this@KPrefBuilderAndroid, + KPrefStringTransaction, + postSetter + ) + + override fun KPref.kprefSingle(key: String) = + KPrefSingleDelegateAndroid(key, this, this@KPrefBuilderAndroid) + + override fun KPref.deleteKeys(keys: Array) { + // Remove pref listing + sp.edit().apply { + keys.forEach { remove(it) } + }.apply() + // Clear cached values + keys.forEach { prefMap[it]?.invalidate() } + } } object KPrefBuilderInMemory : KPrefBuilder { @@ -80,11 +167,20 @@ object KPrefBuilderInMemory : KPrefBuilder { override fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit) = KPrefDelegateInMemory(key, fallback, this, postSetter) - override fun KPref.kpref(key: String, fallback: Set, postSetter: (value: Set) -> Unit) = + override fun KPref.kpref( + key: String, + fallback: Set, + postSetter: (value: Set) -> Unit + ) = KPrefDelegateInMemory(key, fallback, this, postSetter) override fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit) = KPrefDelegateInMemory(key, fallback, this, postSetter) override fun KPref.kprefSingle(key: String) = KPrefSingleDelegateInMemory(key, this) + + override fun KPref.deleteKeys(keys: Array) { + // Clear cached values + keys.forEach { prefMap[it]?.invalidate() } + } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt index 684b139..d54c54d 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt @@ -15,6 +15,7 @@ */ package ca.allanwang.kau.kpref +import android.content.SharedPreferences import ca.allanwang.kau.kotlin.ILazyResettable /** @@ -35,19 +36,22 @@ class KPrefDelegateAndroid internal constructor( private val key: String, private val fallback: T, private val pref: KPref, + private val prefBuilder: KPrefBuilderAndroid, private val transaction: KPrefTransaction, private var postSetter: (value: T) -> Unit = {} ) : KPrefDelegate { private object UNINITIALIZED + private val sp: SharedPreferences get() = prefBuilder.sp + @Volatile private var _value: Any? = UNINITIALIZED private val lock = this init { if (pref.prefMap.containsKey(key)) - throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}") + throw KPrefException("$key is already used elsewhere in preference ${pref.preferenceName}") pref.prefMap[key] = this@KPrefDelegateAndroid } @@ -67,7 +71,7 @@ class KPrefDelegateAndroid internal constructor( if (_v2 !== UNINITIALIZED) { _v2 as T } else { - _value = transaction.get(pref.sp, key, fallback) + _value = transaction.get(sp, key, fallback) _value as T } } @@ -79,7 +83,7 @@ class KPrefDelegateAndroid internal constructor( override operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T) { _value = t - val editor = pref.sp.edit() + val editor = sp.edit() transaction.set(editor, key, t) editor.apply() postSetter(t) @@ -101,7 +105,7 @@ class KPrefDelegateInMemory internal constructor( init { if (pref.prefMap.containsKey(key)) - throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}") + throw KPrefException("$key is already used elsewhere in preference ${pref.preferenceName}") pref.prefMap[key] = this } diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefFactory.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefFactory.kt new file mode 100644 index 0000000..0c49b88 --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefFactory.kt @@ -0,0 +1,22 @@ +package ca.allanwang.kau.kpref + +import android.content.Context + +interface KPrefFactory { + fun createBuilder(preferenceName: String): KPrefBuilder +} + +/** + * Default factory for Android preferences + */ +class KPrefFactoryAndroid(context: Context) : KPrefFactory { + + val context: Context = context.applicationContext + + override fun createBuilder(preferenceName: String): KPrefBuilder = + KPrefBuilderAndroid(context.getSharedPreferences(preferenceName, Context.MODE_PRIVATE)) +} + +object KPrefFactoryInMemory : KPrefFactory { + override fun createBuilder(preferenceName: String): KPrefBuilder = KPrefBuilderInMemory +} \ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt index ae1f855..9d03a16 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt @@ -15,6 +15,7 @@ */ package ca.allanwang.kau.kpref +import android.content.SharedPreferences import ca.allanwang.kau.kotlin.ILazyResettable /** @@ -29,16 +30,19 @@ interface KPrefSingleDelegate : ILazyResettable class KPrefSingleDelegateAndroid internal constructor( private val key: String, - private val pref: KPref + private val pref: KPref, + private val prefBuilder: KPrefBuilderAndroid ) : KPrefSingleDelegate { @Volatile private var _value: Boolean? = null private val lock = this + private val sp: SharedPreferences get() = prefBuilder.sp + init { if (pref.prefMap.containsKey(key)) - throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}") + throw KPrefException("$key is already used elsewhere in preference ${pref.preferenceName}") pref.prefMap[key] = this } @@ -57,9 +61,9 @@ class KPrefSingleDelegateAndroid internal constructor( if (_v2 != null) { _v2 } else { - _value = pref.sp.getBoolean(key, true) + _value = sp.getBoolean(key, true) if (_value!!) { - pref.sp.edit().putBoolean(key, false).apply() + sp.edit().putBoolean(key, false).apply() _value = false true } else false @@ -82,7 +86,7 @@ class KPrefSingleDelegateInMemory internal constructor( init { if (pref.prefMap.containsKey(key)) - throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}") + throw KPrefException("$key is already used elsewhere in preference ${pref.preferenceName}") pref.prefMap[key] = this } -- cgit v1.2.3 From ce0ae639188dad9ca212667c59131c04de1ed575 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 18 Feb 2020 01:37:32 -0800 Subject: Add koin modules for pref injection --- sample/build.gradle | 3 ++ .../ca/allanwang/kau/sample/KPrefViewTest.kt | 40 ++++++++++++---- .../ca/allanwang/kau/sample/SampleTestApp.kt | 13 ++++++ .../kotlin/ca/allanwang/kau/sample/AnimActivity.kt | 5 +- .../kotlin/ca/allanwang/kau/sample/KPrefSample.kt | 3 +- .../kotlin/ca/allanwang/kau/sample/MainActivity.kt | 53 ++++++++++++---------- .../kotlin/ca/allanwang/kau/sample/SampleApp.kt | 30 +++++++++++- 7 files changed, 110 insertions(+), 37 deletions(-) create mode 100644 sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt diff --git a/sample/build.gradle b/sample/build.gradle index 0ed7818..2bd5ba8 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -137,9 +137,11 @@ dependencies { implementation project(':mediapicker') implementation Dependencies.materialDialog("input") + implementation Dependencies.koin testImplementation Dependencies.kotlinTest testImplementation Dependencies.junit + testImplementation Dependencies.koinTest androidTestImplementation Dependencies.kotlinTest androidTestImplementation Dependencies.espresso @@ -147,4 +149,5 @@ dependencies { androidTestImplementation Dependencies.espresso("contrib") androidTestImplementation Dependencies.testRules androidTestImplementation Dependencies.testRunner + androidTestImplementation Dependencies.koinTest } diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt index 72199cf..5847a94 100644 --- a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt @@ -26,6 +26,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withChild import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule import org.hamcrest.BaseMatcher import org.hamcrest.Description @@ -35,6 +36,15 @@ import org.hamcrest.Matchers.instanceOf import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.koin.android.ext.koin.androidContext +import org.koin.core.context.startKoin +import org.koin.core.context.stopKoin +import org.koin.test.KoinTest +import org.koin.test.inject +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.assertFalse +import kotlin.test.assertTrue /** * Created by Allan Wang on 21/12/2018. @@ -43,11 +53,26 @@ import org.junit.runner.RunWith */ @RunWith(AndroidJUnit4::class) @MediumTest -class KPrefViewTest { +class KPrefViewTest : KoinTest { @get:Rule val activity: ActivityTestRule = ActivityTestRule(MainActivity::class.java) + @BeforeTest + fun before() { + startKoin { + androidContext(InstrumentationRegistry.getInstrumentation().context) + modules(listOf(SampleApp.prefModule(), SampleTestApp.prefFactoryModule())) + } + } + + @AfterTest + fun after() { + stopKoin() + } + + private val pref: KPrefSample by inject() + fun verifyCheck(checked: Boolean): Matcher { return object : BoundedMatcher(View::class.java) { @@ -93,11 +118,11 @@ class KPrefViewTest { fun basicCheckboxToggle() { val checkbox1 = onCheckboxView(withChild(withText(R.string.checkbox_1))) - val initiallyChecked = KPrefSample.check1 + assertTrue(pref.check1, "check1 not normalized") - checkbox1.verifyCheck("checkbox1 init", initiallyChecked) + checkbox1.verifyCheck("checkbox1 init", true) checkbox1.perform(click()) - checkbox1.verifyCheck("checkbox1 after click", !initiallyChecked) + checkbox1.verifyCheck("checkbox1 after click", false) } /** @@ -109,11 +134,8 @@ class KPrefViewTest { val checkbox3 = onCheckboxView(withChild(withText(R.string.checkbox_3)), withChild(withText(R.string.desc_dependent))) - // normalize so that both are checked - if (!KPrefSample.check2) - checkbox2.perform(click()) - if (!KPrefSample.check3) - checkbox3.perform(click()) + assertFalse(pref.check2, "check2 not normalized") + assertFalse(pref.check3, "check3 not normalized") checkbox3.verifyCheck("checkbox3 init", true, true) checkbox3.perform(click()) diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt new file mode 100644 index 0000000..4b0c4a7 --- /dev/null +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt @@ -0,0 +1,13 @@ +package ca.allanwang.kau.sample + +import ca.allanwang.kau.kpref.KPrefFactory +import ca.allanwang.kau.kpref.KPrefFactoryInMemory +import org.koin.dsl.module + +object SampleTestApp { + fun prefFactoryModule() = module { + single { + KPrefFactoryInMemory + } + } +} \ No newline at end of file diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt index a472f09..bd1039b 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt @@ -28,6 +28,7 @@ import ca.allanwang.kau.utils.fullLinearRecycler import ca.allanwang.kau.utils.startActivity import ca.allanwang.kau.utils.withAlpha import ca.allanwang.kau.utils.withSlideOut +import org.koin.android.ext.android.inject /** * Created by Allan Wang on 2017-06-12. @@ -37,12 +38,14 @@ import ca.allanwang.kau.utils.withSlideOut */ class AnimActivity : KauBaseActivity() { + private val pref: KPrefSample by inject() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val adapter = SingleFastAdapter() setContentView(fullLinearRecycler(adapter).apply { setBackgroundColor( - KPrefSample.bgColor.withAlpha(255) + pref.bgColor.withAlpha(255) ) }) diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt index 80a75bf..97e8075 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt @@ -17,11 +17,12 @@ package ca.allanwang.kau.sample import android.graphics.Color import ca.allanwang.kau.kpref.KPref +import ca.allanwang.kau.kpref.KPrefFactory /** * Created by Allan Wang on 2017-06-07. */ -object KPrefSample : KPref() { +class KPrefSample(factory: KPrefFactory) : KPref("pref_sample", factory = factory) { var version: Int by kpref("version", -1) var textColor: Int by kpref("TEXT_COLOR", Color.WHITE) var accentColor: Int by kpref("ACCENT_COLOR", 0xffff8900.toInt()) diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt index 4fe941b..4cf632f 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt @@ -40,6 +40,7 @@ import ca.allanwang.kau.utils.withSceneTransitionAnimation import ca.allanwang.kau.xml.showChangelog import com.afollestad.materialdialogs.input.input import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial +import org.koin.android.ext.android.inject class MainActivity : KPrefActivity() { @@ -101,9 +102,11 @@ class MainActivity : KPrefActivity() { const val REQUEST_MEDIA = 27 } + private val pref: KPrefSample by inject() + override fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit = { - textColor = KPrefSample::textColor - accentColor = KPrefSample::accentColor + textColor = pref::textColor + accentColor = pref::accentColor } override fun onCreateKPrefs(savedInstanceState: Bundle?): KPrefAdapterBuilder.() -> Unit = { @@ -113,7 +116,7 @@ class MainActivity : KPrefActivity() { /** * This is how the setup looks like with all the proper tags */ - checkbox(title = R.string.checkbox_1, getter = KPrefSample::check1, setter = { KPrefSample.check1 = it }, + checkbox(title = R.string.checkbox_1, getter = pref::check1, setter = { pref.check1 = it }, builder = { descRes = R.string.desc }) @@ -123,25 +126,25 @@ class MainActivity : KPrefActivity() { */ checkbox( R.string.checkbox_2, - KPrefSample::check2, - { KPrefSample.check2 = it; reloadByTitle(R.string.checkbox_3) }) + pref::check2, + { pref.check2 = it; reloadByTitle(R.string.checkbox_3) }) /** * Since the builder is the last argument and is a lambda, we may write the setup cleanly like so: */ - checkbox(R.string.checkbox_3, KPrefSample::check3, { KPrefSample.check3 = it }) { + checkbox(R.string.checkbox_3, pref::check3, { pref.check3 = it }) { descRes = R.string.desc_dependent - enabler = { KPrefSample.check2 } + enabler = { pref.check2 } onDisabledClick = { itemView.context.toast("I am still disabled") } } - colorPicker(R.string.text_color, KPrefSample::textColor, { KPrefSample.textColor = it; reload() }) { + colorPicker(R.string.text_color, pref::textColor, { pref.textColor = it; reload() }) { descRes = R.string.color_custom allowCustom = true } - colorPicker(R.string.accent_color, KPrefSample::accentColor, { - KPrefSample.accentColor = it + colorPicker(R.string.accent_color, pref::accentColor, { + pref.accentColor = it reload() this@MainActivity.navigationBarColor = it toolbarCanvas.ripple(it, RippleCanvas.MIDDLE, RippleCanvas.END, duration = 500L) @@ -150,8 +153,8 @@ class MainActivity : KPrefActivity() { allowCustom = false } - colorPicker(R.string.background_color, KPrefSample::bgColor, { - KPrefSample.bgColor = it; bgCanvas.ripple(it, duration = 500L) + colorPicker(R.string.background_color, pref::bgColor, { + pref.bgColor = it; bgCanvas.ripple(it, duration = 500L) }) { iicon = GoogleMaterial.Icon.gmd_colorize descRes = R.string.color_custom_alpha @@ -159,7 +162,7 @@ class MainActivity : KPrefActivity() { allowCustom = true } - text(R.string.text, KPrefSample::text, { KPrefSample.text = it }) { + text(R.string.text, pref::text, { pref.text = it }) { descRes = R.string.text_desc onClick = { itemView.context.materialDialog { @@ -171,7 +174,7 @@ class MainActivity : KPrefActivity() { } } - seekbar(R.string.seekbar, KPrefSample::seekbar, { KPrefSample.seekbar = it }) { + seekbar(R.string.seekbar, pref::seekbar, { pref.seekbar = it }) { descRes = R.string.kau_lorem_ipsum increments = 5 textViewConfigs = { @@ -215,30 +218,30 @@ class MainActivity : KPrefActivity() { */ checkbox( R.string.checkbox_2, - KPrefSample::check2, - { KPrefSample.check2 = it; reloadByTitle(R.string.checkbox_3) }) { + pref::check2, + { pref.check2 = it; reloadByTitle(R.string.checkbox_3) }) { titleFun = { R.string.checkbox_3 } descRes = R.string.kau_lorem_ipsum } - text(R.string.text, KPrefSample::text, { KPrefSample.text = it }) { + text(R.string.text, pref::text, { pref.text = it }) { descRes = R.string.kau_lorem_ipsum textGetter = { string(R.string.kau_lorem_ipsum) } } - timePicker(R.string.time, KPrefSample::time12, { KPrefSample.time12 = it }) { + timePicker(R.string.time, pref::time12, { pref.time12 = it }) { descRes = R.string.time_desc_12 use24HourFormat = false } - timePicker(R.string.time, KPrefSample::time24, { KPrefSample.time24 = it }) { + timePicker(R.string.time, pref::time24, { pref.time24 = it }) { descRes = R.string.time_desc_24 use24HourFormat = true } } fun subPrefs(): KPrefAdapterBuilder.() -> Unit = { - text(R.string.text, { KPrefSample.text }, { KPrefSample.text = it }) { + text(R.string.text, { pref.text }, { pref.text = it }) { descRes = R.string.text_desc onClick = { itemView.context.materialDialog { @@ -254,11 +257,11 @@ class MainActivity : KPrefActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - bgCanvas.set(KPrefSample.bgColor) - toolbarCanvas.set(KPrefSample.accentColor) - this.navigationBarColor = KPrefSample.accentColor - if (KPrefSample.version < BuildConfig.VERSION_CODE) { - KPrefSample.version = BuildConfig.VERSION_CODE + bgCanvas.set(pref.bgColor) + toolbarCanvas.set(pref.accentColor) + this.navigationBarColor = pref.accentColor + if (pref.version < BuildConfig.VERSION_CODE) { + pref.version = BuildConfig.VERSION_CODE if (!BuildConfig.DEBUG) showChangelog(R.xml.kau_changelog) } diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt index 6e6d718..2537090 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt @@ -16,6 +16,13 @@ package ca.allanwang.kau.sample import android.app.Application +import ca.allanwang.kau.kpref.KPrefFactory +import ca.allanwang.kau.kpref.KPrefFactoryAndroid +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.core.context.startKoin +import org.koin.core.module.Module +import org.koin.dsl.module /** * Created by Allan Wang on 2017-06-08. @@ -23,6 +30,27 @@ import android.app.Application class SampleApp : Application() { override fun onCreate() { super.onCreate() - KPrefSample.initialize(this, "pref_sample") + + startKoin { + if (BuildConfig.DEBUG) { + androidLogger() + } + androidContext(this@SampleApp) + modules(listOf(prefFactoryModule(), prefModule())) + } + } + + companion object { + fun prefFactoryModule(): Module = module { + single { + KPrefFactoryAndroid(get()) + } + } + + fun prefModule(): Module = module { + single { + KPrefSample(get()) + } + } } } -- cgit v1.2.3 From d67d4a1204796377040a1769175d5798ce09408b Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 23 Feb 2020 13:02:25 -0800 Subject: Fix kpref tests --- .../androidTest/kotlin/ca/allanwang/kau/Utils.kt | 7 ++++ .../kotlin/ca/allanwang/kau/kpref/KPrefTest.kt | 38 +++++++++-------- .../main/kotlin/ca/allanwang/kau/kpref/KPref.kt | 6 +++ .../kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt | 21 +++++----- sample/build.gradle | 2 +- .../ca/allanwang/kau/sample/KPrefViewTest.kt | 41 ++++++++---------- .../ca/allanwang/kau/sample/SampleTestApp.kt | 49 +++++++++++++++++++++- .../ca/allanwang/kau/sample/utils/EspressoUtils.kt | 2 + 8 files changed, 113 insertions(+), 53 deletions(-) create mode 100644 core/src/androidTest/kotlin/ca/allanwang/kau/Utils.kt diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/Utils.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/Utils.kt new file mode 100644 index 0000000..33252d6 --- /dev/null +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/Utils.kt @@ -0,0 +1,7 @@ +package ca.allanwang.kau + +import android.content.Context +import androidx.test.platform.app.InstrumentationRegistry + +val context: Context + get() = InstrumentationRegistry.getInstrumentation().context \ No newline at end of file diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt index 04c6444..222f0f5 100644 --- a/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt @@ -16,14 +16,14 @@ package ca.allanwang.kau.kpref import android.annotation.SuppressLint -import android.content.Context -import androidx.test.core.app.ApplicationProvider +import android.content.SharedPreferences import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest -import kotlin.test.assertEquals +import ca.allanwang.kau.context import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import kotlin.test.assertEquals /** * Created by Allan Wang on 2017-08-01. @@ -33,13 +33,11 @@ import org.junit.runner.RunWith class KPrefTest { lateinit var androidPref: TestPref + lateinit var androidSp: SharedPreferences lateinit var memPref: TestPref - class TestPref(builder: KPrefBuilder) : KPref(builder) { - - init { - initialize(ApplicationProvider.getApplicationContext(), "kpref_test_${System.currentTimeMillis()}") - } + class TestPref(factory: KPrefFactory) : + KPref("kpref_test_${System.currentTimeMillis()}", factory) { var postSetterCount: Int = 0 @@ -60,9 +58,10 @@ class KPrefTest { @Before fun init() { - androidPref = TestPref(KPrefBuilderAndroid) - androidPref.sp.edit().clear().commit() - memPref = TestPref(KPrefBuilderInMemory) + androidPref = TestPref(KPrefFactoryAndroid(context)) + androidSp = (androidPref.builder as KPrefBuilderAndroid).sp + androidSp.edit().clear().commit() + memPref = TestPref(KPrefFactoryInMemory) } private fun pref(action: TestPref.() -> Unit) { @@ -70,7 +69,11 @@ class KPrefTest { memPref.action() } - private fun assertPrefEquals(expected: T, actual: TestPref.() -> T, message: String? = null) { + private fun assertPrefEquals( + expected: T, + actual: TestPref.() -> T, + message: String? = null + ) { assertEquals(expected, androidPref.actual(), "Android KPrefs: $message") assertEquals(expected, memPref.actual(), "In Mem KPrefs: $message") } @@ -83,7 +86,7 @@ class KPrefTest { assertPrefEquals("hello", { hello }) assertPrefEquals(3, { set.size }) assertPrefEquals(setOf("po", "ta", "to"), { set }) - assertEquals(0, androidPref.sp.all.size, "Defaults should not be set automatically") + assertEquals(0, androidSp.all.size, "Defaults should not be set automatically") } @Test @@ -93,8 +96,8 @@ class KPrefTest { assertPrefEquals(2, { one }) pref { hello = "goodbye" } assertPrefEquals("goodbye", { hello }) - assertEquals(androidPref.hello, androidPref.sp.getString("hello", "badfallback")) - assertEquals(2, androidPref.sp.all.size) + assertEquals(androidPref.hello, androidSp.getString("hello", "badfallback")) + assertEquals(2, androidSp.all.size) } @SuppressLint("CommitPrefEdits") @@ -104,9 +107,10 @@ class KPrefTest { assertPrefEquals(2, { one }) assertPrefEquals(6, { prefMap.size }, "Prefmap does not have all elements") pref { reset() } // only invalidates our lazy delegate; doesn't change the actual pref - assertPrefEquals(2, { one }, "Kpref did not properly fetch from shared prefs") + assertEquals(1, memPref.one, "Memory Kpref did not invalidate value") + assertEquals(2, androidPref.one, "Android Kpref did not properly fetch from shared prefs") // Android pref only - androidPref.sp.edit().putInt("one", -1).commit() + androidSp.edit().putInt("one", -1).commit() assertEquals(2, androidPref.one, "Lazy kpref should still retain old value") androidPref.reset() assertEquals(-1, androidPref.one, "Kpref did not refetch from shared prefs upon reset") diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt index 2f8a6aa..a45d66d 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt @@ -42,6 +42,12 @@ open class KPref private constructor( internal val prefMap: MutableMap> = mutableMapOf() + fun add(entry : KPrefDelegate<*>) { + if (prefMap.containsKey(entry.key)) + throw KPrefException("${entry.key} is already used elsewhere in preference $preferenceName") + prefMap[entry.key] = entry + } + fun reset() { prefMap.values.forEach { it.invalidate() } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt index d54c54d..c17d3df 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt @@ -27,13 +27,14 @@ import ca.allanwang.kau.kotlin.ILazyResettable */ interface KPrefDelegate : ILazyResettable { + val key: String operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T) } class KPrefException(message: String) : IllegalAccessException(message) class KPrefDelegateAndroid internal constructor( - private val key: String, + override val key: String, private val fallback: T, private val pref: KPref, private val prefBuilder: KPrefBuilderAndroid, @@ -50,9 +51,7 @@ class KPrefDelegateAndroid internal constructor( private val lock = this init { - if (pref.prefMap.containsKey(key)) - throw KPrefException("$key is already used elsewhere in preference ${pref.preferenceName}") - pref.prefMap[key] = this@KPrefDelegateAndroid + pref.add(this) } override fun invalidate() { @@ -79,7 +78,8 @@ class KPrefDelegateAndroid internal constructor( override fun isInitialized(): Boolean = _value !== UNINITIALIZED - override fun toString(): String = if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet." + override fun toString(): String = + if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet." override operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T) { _value = t @@ -91,7 +91,7 @@ class KPrefDelegateAndroid internal constructor( } class KPrefDelegateInMemory internal constructor( - private val key: String, + override val key: String, private val fallback: T, private val pref: KPref, private var postSetter: (value: T) -> Unit = {} @@ -104,13 +104,11 @@ class KPrefDelegateInMemory internal constructor( private val lock = this init { - if (pref.prefMap.containsKey(key)) - throw KPrefException("$key is already used elsewhere in preference ${pref.preferenceName}") - pref.prefMap[key] = this + pref.add(this) } override fun invalidate() { - // No op + _value = UNINITIALIZED } @Suppress("UNCHECKED_CAST") @@ -133,7 +131,8 @@ class KPrefDelegateInMemory internal constructor( override fun isInitialized(): Boolean = _value !== UNINITIALIZED - override fun toString(): String = if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet." + override fun toString(): String = + if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet." override operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T) { _value = t diff --git a/sample/build.gradle b/sample/build.gradle index 2bd5ba8..77165e8 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -26,7 +26,7 @@ android { versionName androidGitVersion.name() versionCode androidGitVersion.code() multiDexEnabled true - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "ca.allanwang.kau.sample.SampleTestRunner" } viewBinding { enabled = true diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt index 5847a94..156b66f 100644 --- a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt @@ -26,7 +26,6 @@ import androidx.test.espresso.matcher.ViewMatchers.withChild import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest -import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule import org.hamcrest.BaseMatcher import org.hamcrest.Description @@ -35,13 +34,11 @@ import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.instanceOf import org.junit.Rule import org.junit.Test +import org.junit.rules.RuleChain +import org.junit.rules.TestRule import org.junit.runner.RunWith -import org.koin.android.ext.koin.androidContext -import org.koin.core.context.startKoin -import org.koin.core.context.stopKoin import org.koin.test.KoinTest import org.koin.test.inject -import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -55,24 +52,18 @@ import kotlin.test.assertTrue @MediumTest class KPrefViewTest : KoinTest { - @get:Rule val activity: ActivityTestRule = ActivityTestRule(MainActivity::class.java) + @get:Rule + val rule: TestRule = RuleChain.outerRule(SampleTestRule()).around(activity) + + private val pref: KPrefSample by inject() + @BeforeTest fun before() { - startKoin { - androidContext(InstrumentationRegistry.getInstrumentation().context) - modules(listOf(SampleApp.prefModule(), SampleTestApp.prefFactoryModule())) - } - } - - @AfterTest - fun after() { - stopKoin() + pref.reset() } - private val pref: KPrefSample by inject() - fun verifyCheck(checked: Boolean): Matcher { return object : BoundedMatcher(View::class.java) { @@ -132,20 +123,24 @@ class KPrefViewTest : KoinTest { fun dependentCheckboxToggle() { val checkbox2 = onCheckboxView(withChild(withText(R.string.checkbox_2))) val checkbox3 = - onCheckboxView(withChild(withText(R.string.checkbox_3)), withChild(withText(R.string.desc_dependent))) + onCheckboxView( + withChild(withText(R.string.checkbox_3)), + withChild(withText(R.string.desc_dependent)) + ) assertFalse(pref.check2, "check2 not normalized") assertFalse(pref.check3, "check3 not normalized") - checkbox3.verifyCheck("checkbox3 init", true, true) + checkbox2.verifyCheck("checkbox2 init", checked = false, enabled = true) + checkbox3.verifyCheck("checkbox3 init", checked = false, enabled = false) checkbox3.perform(click()) - checkbox3.verifyCheck("checkbox3 after click", false, true) + checkbox3.verifyCheck("checkbox3 after disabled click", checked = false, enabled = false) checkbox2.perform(click()) - checkbox2.verifyCheck("checkbox2 after click", false, true) - checkbox3.verifyCheck("checkbox3 after checkbox2 click", false, false) + checkbox2.verifyCheck("checkbox2 after click", checked = true, enabled = true) + checkbox3.verifyCheck("checkbox3 after checkbox2 click", checked = false, enabled = true) checkbox3.perform(click()) - checkbox3.verifyCheck("checkbox3 after disabled click", false, false) + checkbox3.verifyCheck("checkbox3 after enabled click", checked = true, enabled = true) } } diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt index 4b0c4a7..8705fbc 100644 --- a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/SampleTestApp.kt @@ -1,10 +1,57 @@ package ca.allanwang.kau.sample +import android.app.Application +import android.content.Context +import androidx.test.runner.AndroidJUnitRunner import ca.allanwang.kau.kpref.KPrefFactory import ca.allanwang.kau.kpref.KPrefFactoryInMemory +import ca.allanwang.kau.logging.KL +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.core.KoinComponent +import org.koin.core.context.startKoin +import org.koin.core.get import org.koin.dsl.module -object SampleTestApp { +class SampleTestRunner : AndroidJUnitRunner() { + override fun newApplication( + cl: ClassLoader?, + className: String?, + context: Context? + ): Application { + return super.newApplication(cl, SampleTestApp::class.java.name, context) + } +} + +class SampleTestRule : TestRule { + override fun apply(base: Statement, description: Description): Statement = + object : Statement(), KoinComponent { + override fun evaluate() { + + // Reset prefs + val pref: KPrefSample = get() + pref.reset() + + base.evaluate() + } + } +} + +class SampleTestApp : Application() { + override fun onCreate() { + super.onCreate() + startKoin { + if (BuildConfig.DEBUG) { + androidLogger() + } + androidContext(this@SampleTestApp) + modules(listOf(prefFactoryModule(), SampleApp.prefModule())) + } + } + fun prefFactoryModule() = module { single { KPrefFactoryInMemory diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt index 09ad00a..2a6f0a9 100644 --- a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt @@ -15,6 +15,8 @@ */ package ca.allanwang.kau.sample.utils +import android.content.Context +import androidx.test.platform.app.InstrumentationRegistry import org.hamcrest.BaseMatcher import org.hamcrest.Description import org.hamcrest.Matcher -- cgit v1.2.3 From b35098bafd923d44bf751df2fce5f24cdad6f54b Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 23 Feb 2020 13:14:41 -0800 Subject: Update docs --- docs/Changelog.md | 3 ++- docs/Migration.md | 12 ++++++++++++ sample/src/main/res/xml/kau_changelog.xml | 4 ++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index feb5e4a..576ac96 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,7 +1,8 @@ # Changelog -## v5.2.1 +## v5.3.0 * :color: Allow option to disable selected ring +* :core: Breaking KPref changes; see migration ## v5.2.0 * :about: Migrate about libraries to v7.x.x diff --git a/docs/Migration.md b/docs/Migration.md index fb29f7b..b0d0079 100644 --- a/docs/Migration.md +++ b/docs/Migration.md @@ -2,6 +2,18 @@ Below are some highlights on major refactoring/breaking changes +# v5.2.0 + +## KPref + +In an effort to improve testing options, KPref has some updates to allow for in memory preferences during unit tests. +While you can still use KPref like before as an object (provide the `KPrefFactoryAndroid` factory), +it is recommended that you use some sort of dependency injection/service locator to provide the factory. +An example can be found in the sample app test class. + +Also note that to better support in memory preferences, `reset()` will clear the in memory content for both variants, +meaning that in memory preferences will reset to default. Previously, in memory `reset()` did nothing. + # v5.1.0 ## KPref diff --git a/sample/src/main/res/xml/kau_changelog.xml b/sample/src/main/res/xml/kau_changelog.xml index d61fe63..55adabc 100644 --- a/sample/src/main/res/xml/kau_changelog.xml +++ b/sample/src/main/res/xml/kau_changelog.xml @@ -6,9 +6,9 @@ --> - + - + -- cgit v1.2.3 From 0e7e43f7f778a206b0b30c6997c7c36494e6c142 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 23 Feb 2020 13:40:29 -0800 Subject: Add delete keys function --- core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt | 10 +++++++++- core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt index a45d66d..7f75370 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt @@ -42,7 +42,7 @@ open class KPref private constructor( internal val prefMap: MutableMap> = mutableMapOf() - fun add(entry : KPrefDelegate<*>) { + fun add(entry: KPrefDelegate<*>) { if (prefMap.containsKey(entry.key)) throw KPrefException("${entry.key} is already used elsewhere in preference $preferenceName") prefMap[entry.key] = entry @@ -53,4 +53,12 @@ open class KPref private constructor( } operator fun get(key: String): ILazyResettable<*>? = prefMap[key] + + /** + * Exposed key deletion function from builder. + * To avoid recursion, this type uses vararg + */ + fun deleteKeys(vararg keys: String) { + deleteKeys(keys) + } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt index b8fb8ea..7a35ac2 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt @@ -71,7 +71,7 @@ interface KPrefBuilder { /** * Remove keys from pref so they revert to the default */ - fun KPref.deleteKeys(keys: Array) + fun KPref.deleteKeys(keys: Array) } class KPrefBuilderAndroid(val sp: SharedPreferences) : KPrefBuilder { @@ -143,7 +143,7 @@ class KPrefBuilderAndroid(val sp: SharedPreferences) : KPrefBuilder { override fun KPref.kprefSingle(key: String) = KPrefSingleDelegateAndroid(key, this, this@KPrefBuilderAndroid) - override fun KPref.deleteKeys(keys: Array) { + override fun KPref.deleteKeys(keys: Array) { // Remove pref listing sp.edit().apply { keys.forEach { remove(it) } @@ -179,7 +179,7 @@ object KPrefBuilderInMemory : KPrefBuilder { override fun KPref.kprefSingle(key: String) = KPrefSingleDelegateInMemory(key, this) - override fun KPref.deleteKeys(keys: Array) { + override fun KPref.deleteKeys(keys: Array) { // Clear cached values keys.forEach { prefMap[it]?.invalidate() } } -- cgit v1.2.3