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 extender la class enum con una function de extensión
  • ¿Cómo manejar excepciones en Kotlin?
  • Mover la definición de ViewModel al método de nivel de package
  • La aplicación Kotlin no muestra mi matriz json
  • Daga y cnetworkingenciales de inicio de session
  • Vista personalizada de Android renderizado lento con background dibujable
  • Android Kotlin create class implement Parcelable da un error en 'anulación' del método writeToParcel
  • Los files de Kotlin + Dagger 2: Dagger * no generarán
  • ¿Cómo recuperar todos los documentos de la colección Firestre en la class POJO?
  • Reflexión de kotlin para el método de Java que acepta una matriz de class nula
  • ¿Cómo puedo usar más fácilmente las transactions de Jooq en Kotlin?