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?).

  • ¿Interceptar cada elemento de vista inflado?
  • ¿Hay una mejor manera de filter nulo en una list?
  • Establecer el margen de time de ejecución para cualquier vista usando Kotlin
  • Función genérica de extensión de Kotlin con types básicos sin API de reflexión
  • ¿No se puede usar el valor argb color int en Kotlin?
  • Problema de intención en la aplicación de Android de Java a Kotlin
  • (Java + Kotlin) Autocableo: se espera al less 1 bean que califique como candidato de autowire para esta dependencia
  • Comprobación de conectividad no funciona en Android Oreo Kotlin
  • Hacer reference al valor y a los methods de llamada en types de class generics
  • ¿Puedo invocar el complemento noargs de Kotlin desde la command-line o desde Ant?
  • La function de extensión de kotlin no entiende cómo funciona esto