Ignorar setter y establecer propiedad directamente

Tengo una class que escribe un usuario en ShanetworkingPreferences cada vez que se establece:

class UserManager @Inject constructor( val prefs: ShanetworkingPreferences, val jsonAdapter: JsonAdapter<User> ) { companion object { val USER = "user" } var user: User = User() set(value) { field = value prefs.edit().putString(USER, jsonAdapter.toJson(user)).apply() } init { val userString = prefs.getString(USER, null) if (userString != null) { user = jsonAdapter.fromJson(userString) } } } 

Problema: si el usuario está configurado en el bloque de inicio, llama al colocador y escribe al usuario que acabamos de get de las preferences compartidas … a las preferences compartidas.

Pregunta 1: ¿Cómo puedo establecer directamente la propiedad desde el bloque de inicio?

Pregunta 2: ¿Por qué tengo que inicializar al usuario cuando defino un configurador personalizado, pero puedo omitir la initialization cuando se utiliza el configurador pnetworkingeterminado?

Necesita iniciar directamente la propiedad con el valor correcto. Puede hacerlo utilizando la function de run desde stdlib:

 class UserManager @Inject constructor( val prefs: ShanetworkingPreferences, val jsonAdapter: JsonAdapter<User> ) { companion object { val USER = "user" } var user: User = run { val userString = prefs.getString(USER, null) if (userString != null) { jsonAdapter.fromJson(userString) } else { User() } } set(value) { field = value prefs.edit().putString(USER, jsonAdapter.toJson(user)).apply() } } 

Sintaxis más breve propuesta por Ilya Ryzhenkov sobre Kotlin Slack:

 var user: User = prefs.getString(USER, null)?.let { jsonAdapter.fromJson(it) } ?: User() set(value) { field = value prefs.edit().putString(USER, jsonAdapter.toJson(user)).apply() } 

Creo que la mejor solución es usar el concepto de 'propiedad de respaldo' descrito aquí: https://kotlinlang.org/docs/reference/properties.html#backing-properties

 private var _table: Map<String, Int>? = null public val table: Map<String, Int> get() { if (_table == null) _table = HashMap() // Type parameters are infernetworking return _table ?: throw AssertionError("Set to null by another thread") } 

A continuación, inicialice la propiedad de respaldo en el constructor y haga <backingproperty> = value lugar de field = value , así como apunte el getter a la propiedad de respaldo.

Eche un vistazo al delegado de by map , parece que este es el patrón que desea:

 class User(val map: MutableMap<String, Any?>) { var name: String by map var age: Int by map } 

https://kotlinlang.org/docs/reference/delegated-properties.html#storing-properties-in-a-map

  • ¿Cómo puedo hacer que IntelliJ refactor-> cambie el nombre del parámetro y cambie el nombre de la versión local del mismo? (Kotlin)
  • ¿Cómo desactivar el keyboard cuando hago clic en EditText?
  • Acerca de Kotlin y funciones
  • Administrar objects dentro de actividades para evitar el uso de nulos
  • ¿Cómo get ResultSet string array?
  • FragmentStatePagerAdapter for Nested Pager (en fragment de la navigation inferior) está vacío
  • ¿Cómo puedo probar AsyncTask no llamado?
  • Tiempo de espera en las testings de espresso, la testing no se ejecuta
  • Cómo instanciar una nueva instancia de tipo genérico
  • La reference obligatoria enlazada no funciona con Reactor Subscribe
  • Funciona butterknife 7.x con Kotlin M14?