Kotlin "El reparto inteligente es imposible, porque la propiedad podría haberse cambiado en este momento"

Por qué Android Studio muestra un error cuando uso el script No.2. No encontré diferente entre 1 y 2.

class Adapter { var nameList : ArrayList<String>? = null } class Program { private fun send() { val list: ArrayList<String> = ArrayList() val adapter = Adapter() // Case 1 var otherList = adapter.nameList if (otherList != null) { list.addAll(otherList) // <--- no error } // Case 2 if (adapter.nameList!=null) { list.addAll(adapter.nameList) // <--- Error here // Smart cast to 'kotlin.collections.ArrayList<String> /* = java.util.ArrayList<String> */' is impossible, because 'adapter.nameList' is a mutable property that could have been changed by this time } } } 

Por favor explica este caso

El IDE debería darle una advertencia, explicando que después de la comprobación nula, es posible que adapter.nameList haya cambiado por otro hilo, y que cuando llame a list.addAll(adapter.nameList) , adapter.nameList podría ser nulo por ese adapter.nameList punto (de nuevo, porque un hilo diferente podría haber cambiado el valor. Esta sería una condición de carrera).

Tienes algunas soluciones:

  1. Haga que nameList val , lo que lo convierte en reference final . Como es final, se garantiza que otro hilo no puede cambiarlo. Esto probablemente no se ajusta a su caso de uso.

     class Adapter { val nameList : ArrayList<String>? = null } 
  2. Crea una copy local de la list de nombres antes de hacer la verificación. Debido a que es una copy local, el comstackdor sabe que otro hilo no puede acceder a él y, por lo tanto, no puede modificarse. La copy local podría definirse con var o val en este caso, pero recomiendo val .

     val nameList = adapter.nameList if (nameList != null) { list.addAll(nameList) } 
  3. Use una de las funciones de utilidad que proporciona Kotlin para un caso como este. La function let copy la reference a la que se llama como un parámetro utilizando una function en línea. Esto significa que se comstack efectivamente para ser igual que el # 2, pero es un poco más escueto. Yo prefiero esta solución.

     adapter.nameList?.let { list.addAll(it) } 

'adapter.nameList' is a mutable property that could have been changed

El motivo de esta comprobación y post de error son los hilos . Lo que tienes se llama una condición de carrera. En muchos casos similares, es posible que otro hilo cambie el valor de adapter.namelist entre el control de nulidad y el list.addAll llamada. Claramente, esto no puede suceder en su caso, ya que el adaptador no se ha filtrado de la function de envío, pero supongo que el comstackdor no es lo suficientemente inteligente como para saberlo.

En contraste, no existe una condición de carrera en el caso 1 ya que la list de nombres solo se accede una vez.

Además, esto no puede suceder si la list de namelist es val lugar de var , ya que el comstackdor sabe entonces que no puede cambiar, por lo que no puede cambiar de no nulo a nulo.

Your adapter.nameList es una propiedad mutable así que conviértalo en inmutable.

Utilizar esta

  val nameList : ArrayList<String>? = null 

En lugar de esto

  var nameList : ArrayList<String>? = null 

O también puedes resolver este problema mediante la afirmación de Assert no nulo

  list.addAll(adapter.nameList!!) 

Nota: – !! se evalúa en time de ejecución, es solo un operador.

La expresión (x !!)

arroja una KotlinNullPointerException si x == null, de lo contrario, devuelve x cast para el tipo correspondiente que no admite nulos (por ejemplo, lo devuelve como una cadena cuando se llama a una variable con tipo String?).

  • Kotlin: ¿Cómo hacer el menu de la barra de herramientas con Anko DSL?
  • El complemento de Klotlin-Spring de Gradle no abre classs de spring
  • Maneras de ofuscar el acceso a miembros de la class preferentemente privados, pero en realidad públicos, con el fin de utilizarlos en methods en línea
  • Android Room Persistences library y Kotlin
  • Spring ConfigurationProperties y Kotlin?
  • ¿Cómo guardo un logging en Apache Jena?
  • Comtesting si mi actividad está en MultiWindowMode o no está usando Kotlin
  • Kotlin no funciona en Android Studio
  • La aplicación se bloquea al generar la stack de nuevo
  • Wicket NumberTextField en Kotlin lanza ClassCastException cuando se envía
  • Herencia explícita de Any in Kotlin - ¿Puede y cómo se hace?