Skip to content

Commit

Permalink
improve preference
Browse files Browse the repository at this point in the history
  • Loading branch information
steadymoka committed Oct 23, 2020
1 parent fef5e8f commit ea5d93f
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 2 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package land.moka.kmm.shared.lib.preferecne

import android.content.Context
import android.content.SharedPreferences
import land.moka.kmm.shared.lib.util.application

actual class Preference {

private val sharedPreferences: SharedPreferences

actual constructor(name: String?) {
sharedPreferences = application.getSharedPreferences(name, Context.MODE_PRIVATE)
}

actual fun setInt(key: String, value: Int) {
sharedPreferences.edit().putInt(key, value).apply()
}

actual fun getInt(key: String, defaultValue: Int): Int {
return sharedPreferences.getInt(key, defaultValue)
}

actual fun getInt(key: String): Int? {
return if (hasKey(key)) {
sharedPreferences.getInt(key, 0)
} else {
null
}
}

actual fun setFloat(key: String, value: Float) {
sharedPreferences.edit().putFloat(key, value).apply()
}

actual fun getFloat(key: String, defaultValue: Float): Float {
return sharedPreferences.getFloat(key, defaultValue)
}

actual fun getFloat(key: String): Float? {
return if (hasKey(key)) {
sharedPreferences.getFloat(key, 0f)
} else {
null
}
}

actual fun setLong(key: String, value: Long) {
sharedPreferences.edit().putLong(key, value).apply()
}

actual fun getLong(key: String, defaultValue: Long): Long {
return sharedPreferences.getLong(key, defaultValue)
}

actual fun getLong(key: String): Long? {
return if (hasKey(key)) {
sharedPreferences.getLong(key, 0)
} else {
null
}
}

actual fun setString(key: String, value: String) {
sharedPreferences.edit().putString(key, value).apply()
}

actual fun getString(key: String, defaultValue: String): String {
return sharedPreferences.getString(key, defaultValue) ?: defaultValue
}

actual fun getString(key: String): String? {
return if (hasKey(key)) {
sharedPreferences.getString(key, "")
} else {
null
}
}

actual fun getBoolean(key: String, defaultValue: Boolean): Boolean {
return sharedPreferences.getBoolean(key, defaultValue)
}

actual fun getBoolean(key: String): Boolean? {
return if (hasKey(key)) {
sharedPreferences.getBoolean(key, false)
} else {
null
}
}

actual fun setBoolean(key: String, value: Boolean) {
sharedPreferences.edit().putBoolean(key, value).apply()
}

actual fun hasKey(key: String): Boolean = sharedPreferences.contains(key)

actual fun clear() {
sharedPreferences.edit().clear().apply()
}

actual fun remove(key: String) {
if (hasKey(key))
sharedPreferences.edit().remove(key).apply()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package land.moka.kmm.shared.lib.util

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.app.Service
import android.app.backup.BackupAgent
import android.content.ContentProvider
import android.content.ContentValues
import android.content.Context
import android.content.ContextWrapper
import android.database.Cursor
import android.net.Uri

@SuppressLint("StaticFieldLeak")
private var appContext: Context? = null

val application: Context
get() = appContext ?: initAndGetAppCtxWithReflection()

/**
* This method will return true on [Context] implementations known to be able to leak memory.
* This includes [Activity], [Service], the lesser used and lesser known [BackupAgent], as well as
* any [ContextWrapper] having one of these as its base context.
*/
fun Context.canLeakMemory(): Boolean = when (this) {
is Application -> false
is Activity, is Service, is BackupAgent -> true
is ContextWrapper -> if (baseContext === this) true else baseContext.canLeakMemory()
else -> applicationContext === null
}

/**
* This methods is only run if [appCtx] is accessed while [AppCtxInitProvider] hasn't been
* initialized. This may happen in case you're accessing it outside the default process, or in case
* you are accessing it in a [ContentProvider] with a higher priority than [AppCtxInitProvider]
* (900 at the time of writing this doc).
*
* If you don't want this code that uses reflection to ever run, see [injectAsAppCtx].
*/
@SuppressLint("PrivateApi")
private fun initAndGetAppCtxWithReflection(): Context {
// Fallback, should only run once per non default process.
val activityThread = Class.forName("android.app.ActivityThread")
val ctx = activityThread.getDeclaredMethod("currentApplication").invoke(null) as Context
appContext = ctx
return ctx
}

class AppContextProvider : ContentProvider() {
override fun onCreate(): Boolean {
val context = context
require(!(context?.canLeakMemory() ?: true)) { "The passed Context($this) would leak memory!" }
appContext = context
return true
}

override fun insert(uri: Uri, values: ContentValues?): Uri {
throw Exception("unimplemented")
}

override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor {
throw Exception("unimplemented")
}

override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?): Int {
throw Exception("unimplemented")
}

override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
throw Exception("unimplemented")
}

override fun getType(uri: Uri): String {
throw Exception("unimplemented")
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package land.moka.kmm.shared.di.module

import land.moka.kmm.shared.lib.preferecne.Preference
import org.kodein.di.DI
import org.kodein.di.bind
import org.kodein.di.singleton

val databaseModule = DI.Module("database") {

}
bind<Preference>() with singleton {
Preference()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package land.moka.kmm.shared.lib.preferecne

expect class Preference(name: String? = null) {

fun setInt(key: String, value: Int)
fun getInt(key: String, defaultValue: Int): Int
fun getInt(key: String): Int?

fun setFloat(key: String, value: Float)
fun getFloat(key: String, defaultValue: Float): Float
fun getFloat(key: String): Float?

fun setLong(key: String, value: Long)
fun getLong(key: String, defaultValue: Long): Long
fun getLong(key: String): Long?

fun setString(key: String, value: String)
fun getString(key: String, defaultValue: String): String
fun getString(key: String): String?

fun setBoolean(key: String, value: Boolean)
fun getBoolean(key: String, defaultValue: Boolean): Boolean
fun getBoolean(key: String): Boolean?

fun remove(key: String)
fun clear()

fun hasKey(key: String): Boolean

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package land.moka.kmm.shared.lib.preferecne

import platform.Foundation.NSUserDefaults

actual class Preference {

private val userDefault: NSUserDefaults

actual constructor(name: String?) {
userDefault = NSUserDefaults(suiteName = name)
}

actual fun setInt(key: String, value: Int) {
return userDefault.setInteger(value.toLong(), key)
}

actual fun getInt(key: String, defaultValue: Int): Int {
return if (hasKey(key)) {
userDefault.integerForKey(key).toInt()
} else {
defaultValue
}
}

actual fun getInt(key: String): Int? {
return if (hasKey(key)) {
userDefault.integerForKey(key).toInt()
} else {
null
}
}

actual fun setFloat(key: String, value: Float) {
return userDefault.setFloat(value, key)
}

actual fun getFloat(key: String, defaultValue: Float): Float {
return if (hasKey(key)) {
userDefault.floatForKey(key)
} else {
defaultValue
}
}

actual fun getFloat(key: String): Float? {
return if (hasKey(key)) {
userDefault.floatForKey(key)
} else {
null
}
}

actual fun setLong(key: String, value: Long) {
return userDefault.setInteger(value, key)
}

actual fun getLong(key: String, defaultValue: Long): Long {
return if (hasKey(key)) {
userDefault.integerForKey(key)
} else {
defaultValue
}
}

actual fun getLong(key: String): Long? {
return if (hasKey(key)) {
userDefault.integerForKey(key)
} else {
null
}
}

actual fun setString(key: String, value: String) {
return userDefault.setObject(value, key)
}

actual fun getString(key: String, defaultValue: String): String {
return userDefault.stringForKey(key) ?: defaultValue
}

actual fun getString(key: String): String? {
return if (hasKey(key)) {
userDefault.stringForKey(key) ?: ""
} else {
null
}
}

actual fun setBoolean(key: String, value: Boolean) {
return userDefault.setBool(value, key)
}

actual fun getBoolean(key: String, defaultValue: Boolean): Boolean {
return if (hasKey(key)) {
userDefault.boolForKey(key)
} else {
defaultValue
}
}

actual fun getBoolean(key: String): Boolean? {
return if (hasKey(key)) {
userDefault.boolForKey(key)
} else {
null
}
}

actual fun hasKey(key: String): Boolean = userDefault.objectForKey(key) != null

actual fun clear() {
for (key in userDefault.dictionaryRepresentation().keys) {
remove(key as String)
}
}

actual fun remove(key: String) {
userDefault.removeObjectForKey(key)
}

}

0 comments on commit ea5d93f

Please sign in to comment.