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

  • Es `foo como? Foo` un equivalente completo de 'foo como Foo? `En kotlin?
  • ¿Cómo puedo descartar la alerta después de hacer clic en el button Atrás?
  • Error: no se encontró el procesador de annotations '__gen.AnnotationProcessorWrapper_debug_android_databinding_annotationprocessor_ProcessDataBinding'
  • La compilation de Kotlin falló en Android Studio
  • ¿Cómo hacer un tipo comparable de Kotlin?
  • Cómo especificar "propio tipo" como tipo de devolución en Kotlin
  • El argumento de tipo genérico no está dentro de los límites
  • Kotlin: ¿Cómo puedo invocar un campo lambda que tiene un tipo genérico de su class?
  • Una expresión regular que reconocería a / * ... * / note
  • ¿Cómo puedo usar un model de vista, con sqlite y un receptor de difusión para actualizar la UI?
  • Clase de aplicación Kotlin SingleTon