2

I have tiny wrapper around SharedPreferences written in Kotlin. I use Gson for setting and getting not primitive types. Now I would like to migrate this class to work with Moshi, but I do not understand how to work with generics in Moshi.

package com.example.extensions

import android.content.Context
import android.content.SharedPreferences
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken

object Preferences {

    lateinit var preferences: SharedPreferences

    val json = GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create()!!

    fun init(context: Context) {
        preferences = context.getSharedPreferences(
            context.packageName + ".preferences",
            Context.MODE_PRIVATE
        )
    }

    inline fun <reified T> get(key: String, defaultValue: T? = null): T? {
        return when (T::class) {
            String::class -> preferences.getString(key, defaultValue as? String) as T?
            Int::class -> preferences.getInt(key, defaultValue as? Int ?: -1) as T?
            Boolean::class -> preferences.getBoolean(key, defaultValue as? Boolean ?: false) as T?
            Float::class -> preferences.getFloat(key, defaultValue as? Float ?: -1f) as T?
            Long::class -> preferences.getLong(key, defaultValue as? Long ?: -1) as T?
            else -> {
                val value = preferences.getString(key, null)
                if (value == null)
                    defaultValue else
                    json.fromJson<T>(value, object: TypeToken<T>(){}.type)
            }
        }
    }

    fun <T> set(key: String, value: T) {
        when (value) {
            is String? -> edit { putString(key, value) }
            is Int -> edit { putInt(key, value) }
            is Boolean -> edit { putBoolean(key, value) }
            is Float -> edit { putFloat(key, value) }
            is Long -> edit { putLong(key, value) }
            else -> edit { putString(key, json.toJson(value)) }
        }
    }

    private fun edit(operation: SharedPreferences.Editor.() -> Unit) {
        val editor = preferences.edit()
        operation(editor)
        editor.apply()
    }

    fun reset(): Boolean {
        return preferences.edit().clear().commit()
    }

}

I tried this, but I'm getting an error:

package com.mezhevikin.converter.extensions

import android.content.Context
import android.content.SharedPreferences
import com.squareup.moshi.Moshi

object Preferences {

    lateinit var preferences: SharedPreferences

    val moshi: Moshi = Moshi.Builder().build()

    fun init(context: Context) {
        preferences = context.getSharedPreferences(
            context.packageName + ".preferences",
            Context.MODE_PRIVATE
        )
    }

    inline fun <reified T> get(key: String, defaultValue: T? = null): T? {
        return when (T::class) {
            String::class -> preferences.getString(key, defaultValue as? String) as T?
            Int::class -> preferences.getInt(key, defaultValue as? Int ?: -1) as T?
            Boolean::class -> preferences.getBoolean(key, defaultValue as? Boolean ?: false) as T?
            Float::class -> preferences.getFloat(key, defaultValue as? Float ?: -1f) as T?
            Long::class -> preferences.getLong(key, defaultValue as? Long ?: -1) as T?
            else -> {
                val value = preferences.getString(key, null)
                if (value == null)
                    defaultValue else
                    moshi.adapter(T::class.java).fromJson(value)
            }
        }
    }

    fun <T: Any> set(key: String, value: T?) {
        when (value) {
            is String? -> edit { putString(key, value) }
            is Int -> edit { putInt(key, value) }
            is Boolean -> edit { putBoolean(key, value) }
            is Float -> edit { putFloat(key, value) }
            is Long -> edit { putLong(key, value) }
            else -> edit { putString(key, moshi.adapter(value!!.javaClass).toJson(value)) }
        }
    }

    private fun edit(operation: SharedPreferences.Editor.() -> Unit) {
        val editor = preferences.edit()
        operation(editor)
        editor.apply()
    }

    fun reset(): Boolean {
        return preferences.edit().clear().commit()
    }

}

Error: Caused by: java.lang.IllegalArgumentException: Expected at least one @ToJson or @FromJson method on java.lang.Class

nullproduction
  • 576
  • 3
  • 18

0 Answers0