Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added moshi support #262

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ dependencies {
// optional, support saving json string through Gson
implementation 'com.chibatching.kotpref:gson-support:2.13.1'
implementation 'com.google.code.gson:gson:2.8.6'

// optional, support saving json string through Moshi
implementation 'com.chibatching.kotpref:moshi-support:2.13.1'
implementation 'com.squareup.moshi:moshi:1.13.0'
// optional to moshi
implementation 'com.squareup.moshi:moshi-adapters:1.13.0'
kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.13.0'

// optional, support LiveData observable preference
implementation 'com.chibatching.kotpref:livedata-support:2.13.1'
Expand Down
4 changes: 4 additions & 0 deletions buildSrc/src/main/java/dependencies/Deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ object Deps {

const val gson = "com.google.code.gson:gson:${Versions.gson}"

const val moshi = "com.squareup.moshi:moshi:${Versions.moshi}"
const val moshiAdapters = "com.squareup.moshi:moshi-adapters:${Versions.moshi}"
const val moshiKapt = "com.squareup.moshi:moshi-kotlin-codegen:${Versions.moshi}"

object Kotlin {
const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}"
const val gradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/java/dependencies/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ object Versions {
internal const val junit = "4.13.2"
internal const val robolectric = "4.7.3"
internal const val gson = "2.8.9"
internal const val moshi = "1.13.0"

internal const val androidGradlePlugin = "7.0.4"
internal const val dokka = "1.6.10"
Expand Down
1 change: 1 addition & 0 deletions moshi-support/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
16 changes: 16 additions & 0 deletions moshi-support/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Module moshi-support

Serialize/Deserialize json object to KotprefModel using Moshi

### Set up

Pass the application context to Kotpref

```kotlin
Kotpref.moshi = Moshi.Builder()
.add(
Date::class.java,
Rfc3339DateJsonAdapter().nullSafe()
) // optional if date needed com.squareup.moshi:moshi-adapters
.build()
```
74 changes: 74 additions & 0 deletions moshi-support/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import dependencies.Deps
import dependencies.Versions
import plugin.BuildSettingHelperPlugin

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'org.jetbrains.dokka'
apply plugin: 'jacoco'
apply plugin: BuildSettingHelperPlugin
apply plugin: 'kotlin-kapt'

ext.moduleName = 'Kotpref moshi support'
ext.moduleDescription = "Serialize/Deserialize json object to KotprefModel using Moshi"

android {
compileSdkVersion Versions.targetSdk

defaultConfig {
minSdkVersion Versions.minSdk
targetSdkVersion Versions.targetSdk
versionName Versions.versionName
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
testOptions {
unitTests {
all {
jacoco {
includeNoLocationClasses = true
excludes = ['jdk.internal.*']
}
}
includeAndroidResources = true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
freeCompilerArgs += "-Xexplicit-api=strict"
}
jacoco {
version = Versions.jacoco
}
}

dependencies {
compileOnly Deps.Kotlin.stdlib
api project(":kotpref")

compileOnly Deps.moshi

testImplementation Deps.Kotlin.stdlib
testImplementation Deps.moshi
testImplementation Deps.moshiAdapters
kaptTest Deps.moshiKapt
testImplementation Deps.junit
testImplementation Deps.robolectric
testImplementation Deps.AndroidX.testCore
testImplementation Deps.truth

dokkaHtmlPlugin Deps.dokkaJava
}

apply from: "${project.rootDir}/gradle/publish/publish.gradle"
17 changes: 17 additions & 0 deletions moshi-support/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/takao-chiba/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
3 changes: 3 additions & 0 deletions moshi-support/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<manifest package="com.chibatching.kotpref.moshipref">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.chibatching.kotpref.moshipref

import com.chibatching.kotpref.Kotpref
import com.chibatching.kotpref.KotprefModel
import com.chibatching.kotpref.pref.AbstractPref
import com.squareup.moshi.Moshi

/**
* Moshi object to serialize and deserialize delegated property
*/
public var Kotpref.moshi: Moshi?
get() {
return KotprefMoshiHolder.moshi
}
set(value) {
KotprefMoshiHolder.moshi = value
}

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value
* @param key custom preferences key
*/
public inline fun <reified T : Any> KotprefModel.moshiPref(
default: T,
key: String? = null,
commitByDefault: Boolean = commitAllPropertiesByDefault
): AbstractPref<T> = MoshiPref(T::class.java, default, key, commitByDefault)

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value provider function
* @param key custom preferences key
*/
public inline fun <reified T : Any> KotprefModel.moshiPref(
key: String? = null,
commitByDefault: Boolean = commitAllPropertiesByDefault,
noinline default: () -> T
): AbstractPref<T> = MoshiPref(T::class.java, default, key, commitByDefault)

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value
* @param key custom preferences key resource id
*/
public inline fun <reified T : Any> KotprefModel.moshiPref(
default: T,
key: Int,
commitByDefault: Boolean = commitAllPropertiesByDefault
): AbstractPref<T> =
MoshiPref(T::class.java, default, context.getString(key), commitByDefault)

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value provider function
* @param key custom preferences key resource id
*/
public inline fun <reified T : Any> KotprefModel.moshiPref(
key: Int,
commitByDefault: Boolean = commitAllPropertiesByDefault,
noinline default: () -> T
): AbstractPref<T> =
MoshiPref(T::class.java, default, context.getString(key), commitByDefault)

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value
* @param key custom preferences key
*/
public inline fun <reified T : Any> KotprefModel.moshiNullablePref(
default: T? = null,
key: String? = null,
commitByDefault: Boolean = commitAllPropertiesByDefault
): AbstractPref<T?> =
MoshiNullablePref(T::class.java, default, key, commitByDefault)

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value provider function
* @param key custom preferences key
*/
public inline fun <reified T : Any> KotprefModel.moshiNullablePref(
key: String? = null,
commitByDefault: Boolean = commitAllPropertiesByDefault,
noinline default: (() -> T?)
): AbstractPref<T?> =
MoshiNullablePref(T::class.java, default, key, commitByDefault)

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value
* @param key custom preferences key resource id
*/
public inline fun <reified T : Any> KotprefModel.moshiNullablePref(
default: T? = null,
key: Int,
commitByDefault: Boolean = commitAllPropertiesByDefault
): AbstractPref<T?> = MoshiNullablePref(
T::class.java,
default,
context.getString(key),
commitByDefault
)

/**
* Delegate shared preferences property serialized and deserialized by moshi
* @param default default moshi object value provider function
* @param key custom preferences key resource id
*/
public inline fun <reified T : Any> KotprefModel.moshiNullablePref(
key: Int,
commitByDefault: Boolean = commitAllPropertiesByDefault,
noinline default: (() -> T?)
): AbstractPref<T?> = MoshiNullablePref(
T::class.java,
default,
context.getString(key),
commitByDefault
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.chibatching.kotpref.moshipref

import com.squareup.moshi.Moshi

internal object KotprefMoshiHolder {
var moshi: Moshi? = null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.chibatching.kotpref.moshipref

import android.content.SharedPreferences
import com.chibatching.kotpref.Kotpref
import com.chibatching.kotpref.execute
import com.chibatching.kotpref.pref.AbstractPref
import java.lang.reflect.Type
import kotlin.reflect.KProperty

public class MoshiNullablePref<T : Any>(
private val targetType: Type,
private val default: (() -> T?),
override val key: String?,
private val commitByDefault: Boolean
) : AbstractPref<T?>() {

public constructor(
targetType: Type,
default: T?,
key: String?,
commitByDefault: Boolean
) : this(targetType, { default }, key, commitByDefault)

override fun getFromPreference(property: KProperty<*>, preference: SharedPreferences): T? {
return preference.getString(preferenceKey, null)?.let { json ->
deserializeFromJson(json) ?: default.invoke()
}
}

override fun setToPreference(property: KProperty<*>, value: T?, preference: SharedPreferences) {
serializeToJson(value).let { json ->
preference.edit().putString(preferenceKey, json).execute(commitByDefault)
}
}

override fun setToEditor(property: KProperty<*>, value: T?, editor: SharedPreferences.Editor) {
serializeToJson(value).let { json ->
editor.putString(preferenceKey, json)
}
}

private fun serializeToJson(value: T?): String? {
return Kotpref.moshi.let {
if (it == null) throw IllegalStateException("Moshi has not been set to Kotpref")

it.adapter<T>(targetType).toJson(value)
}
}

private fun deserializeFromJson(json: String): T? {
return Kotpref.moshi.let {
if (it == null) throw IllegalStateException("Moshi has not been set to Kotpref")

it.adapter<T>(targetType).fromJson(json)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.chibatching.kotpref.moshipref

import android.content.SharedPreferences
import com.chibatching.kotpref.Kotpref
import com.chibatching.kotpref.execute
import com.chibatching.kotpref.pref.AbstractPref
import java.lang.reflect.Type
import kotlin.reflect.KProperty

public class MoshiPref<T : Any>(
private val targetType: Type,
private val default: () -> T,
override val key: String?,
private val commitByDefault: Boolean
) : AbstractPref<T>() {

public constructor(
targetType: Type,
default: T,
key: String?,
commitByDefault: Boolean
) : this(
targetType, { default }, key, commitByDefault
)

override fun getFromPreference(property: KProperty<*>, preference: SharedPreferences): T {
return preference.getString(preferenceKey, null)?.let { json ->
deserializeFromJson(json) ?: default()
} ?: default()
}

override fun setToPreference(property: KProperty<*>, value: T, preference: SharedPreferences) {
serializeToJson(value).let { json ->
preference.edit().putString(preferenceKey, json).execute(commitByDefault)
}
}

override fun setToEditor(property: KProperty<*>, value: T, editor: SharedPreferences.Editor) {
serializeToJson(value).let { json ->
editor.putString(preferenceKey, json)
}
}

private fun serializeToJson(value: T?): String? {
return Kotpref.moshi.let {
if (it == null) throw IllegalStateException("Moshi has not been set to Kotpref")

it.adapter<T>(targetType).toJson(value)
}
}

private fun deserializeFromJson(json: String): T? {
return Kotpref.moshi.let {
if (it == null) throw IllegalStateException("Moshi has not been set to Kotpref")

it.adapter<T>(targetType).fromJson(json)
}
}
}
Loading