Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

330
Views
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 answers
Answer question

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 Report

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 Report

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 Report

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 Report

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!