Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

333
Vistas
MutableLiveData: no se puede invocar setValue en un hilo de fondo de Coroutine

Estoy tratando de activar una actualización en LiveData desde una rutina:

 object AddressList: MutableLiveData<List<Address>>() fun getAddressesLiveData(): LiveData<List<Address>> { AddressList.value = listOf() GlobalScope.launch { AddressList.value = getAddressList() } return AddressList }

pero me sale el siguiente error:

IllegalStateException: no se puede invocar setValue en un hilo de fondo

¿Hay alguna manera de hacer que funcione con coroutines?

over 4 years ago · Santiago Trujillo
7 Respuestas
Responde la pregunta

0

Estaba enfrentando este error cuando llamé a una rutina dentro de runBlockingTest para un caso de prueba

 TestCoroutineRule().runBlockingTest { }

Lo solucioné agregando instantExecutorRule como miembro de la clase

 @get:Rule var instantExecutorRule = InstantTaskExecutorRule()
over 4 years ago · Santiago Trujillo Denunciar

0

Acabo de darme cuenta de que es posible usando withContext(Dispatchers.Main){} :

 object AddressList: MutableLiveData<List<Address>>() fun getAddressesLiveData(): LiveData<List<Address>> { GlobalScope.launch { withContext(Dispatchers.Main){ AddressList.value = getAddressList() } } return AddressList }
over 4 years ago · Santiago Trujillo Denunciar

0

Puede hacer uno de los siguientes:

 object AddressList: MutableLiveData<List<Address>>() fun getAddressesLiveData(): LiveData<List<Address>> { AddressList.value = listOf() GlobalScope.launch { AddressList.postValue(getAddressList()) } return AddressList }

o

 fun getAddressesLiveData(): LiveData<List<Address>> { AddressList.value = listOf() GlobalScope.launch { val adresses = getAddressList() withContext(Dispatchers.Main) { AddressList.value = adresses } } return AddressList }
over 4 years ago · Santiago Trujillo Denunciar

0

Aunque otros han señalado que, en este caso, la biblioteca proporciona su propio método para publicar una operación en el subproceso principal, las corrutinas brindan una solución general que funciona independientemente de la funcionalidad de una biblioteca determinada.

El primer paso es dejar de usar GlobalScope para trabajos en segundo plano, ya que esto dará lugar a fugas en las que su actividad, trabajo programado o cualquier unidad de trabajo desde la que invoque esto puede destruirse y, sin embargo, su trabajo continuará en segundo plano y incluso enviar sus resultados al hilo principal. Esto es lo que dice la documentación oficial sobre GlobalScope :

El código de la aplicación generalmente debe usar CoroutineScope definido por la aplicación; se desaconseja enfáticamente usar async o iniciar en la instancia de GlobalScope.

Debe definir su propio alcance coroutine y su propiedad coroutineContext debe contener Dispatchers.Main como el despachador. Además, todo el patrón de iniciar trabajos dentro de una llamada de función y devolver LiveData (que es básicamente otro tipo de Future ), no es la forma más conveniente de usar rutinas. En su lugar, deberías tener

 suspend fun getAddresses() = withContext(Dispatchers.Default) { getAddressList() }

y en el sitio de la llamada debe launch una corrutina, dentro de la cual ahora puede llamar libremente a getAddresses() como si fuera un método de bloqueo y obtener las direcciones directamente como un valor de retorno.

over 4 years ago · Santiago Trujillo Denunciar

0

Si desea actualizar la interfaz de usuario utilizando Coroutines , hay 2 formas de lograrlo

GlobalScope.launch(Dispatchers.Main):

 GlobalScope.launch(Dispatchers.Main) { delay(1000) // 1 sec delay // call to UI thread }

Y si desea que se realice algún trabajo en segundo plano, pero luego desea actualizar la interfaz de usuario, puede lograrlo de la siguiente manera:

withContext(Dispatchers.Main)

 GlobalScope.launch { delay(1000) // 1 sec delay // do some background task withContext(Dispatchers.Main) { // call to UI thread } }
over 4 years ago · Santiago Trujillo Denunciar

0

Use liveData.postValue(value) en lugar de liveData.value = value . Se llama asíncrono.

De la documentación :

postValue : publica una tarea en un hilo principal para establecer el valor dado.

over 4 years ago · Santiago Trujillo Denunciar

0

En mi caso, tuve que agregar Dispatchers.Main a los argumentos de lanzamiento y funcionó bien:

 val job = GlobalScope.launch(Dispatchers.Main) { delay(1500) search(query) }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda