Editar
Creé un proyecto de demostración en Github que muestra el problema exacto. Proyecto Git .
He escrito un recyclerView expandible en Kotlin . Cada fila tiene un botón de reproducción que usa TextToSpeech . El texto del botón de reproducción debería cambiar para detenerse mientras se está reproduciendo, y luego volver a reproducirse cuando termine.
Cuando llamo notifyItemChanged dentro de onStart y onDone de setOnUtteranceProgressListener , no se llama a onBindViewHolder y las filas en recyclerView ya no se expandirán ni colapsarán correctamente.
t1 = TextToSpeech(context, TextToSpeech.OnInitListener { status -> if (status != TextToSpeech.ERROR) { t1?.setOnUtteranceProgressListener(object : UtteranceProgressListener() { override fun onStart(utteranceId: String?) { recyclerView.adapter.notifyItemChanged(position) } override fun onStop(utteranceId: String?, interrupted: Boolean) { super.onStop(utteranceId, interrupted) onDone(utteranceId) } override fun onDone(utteranceId: String?) { val temp = position position = -1 recyclerView.adapter.notifyItemChanged(temp) } override fun onError(utteranceId: String?) {} // override fun onError(utteranceId: String?, errorCode: Int) { // super.onError(utteranceId, errorCode) // } }) } })en BindViewHolder:
override fun onBindViewHolder(holder: RabbanaDuasViewHolder, position: Int){ if (Values.playingPos == position) { holder.cmdPlay.text = context.getString(R.string.stop_icon) } else { holder.cmdPlay.text = context.getString(R.string.play_icon) } } ¿Cómo puedo llamar a notifyItemChanged(position) desde setOnUtteranceProgressListener o qué devolución de llamada puedo usar para que notificarItemChanged solo se ejecute cuando sea seguro ejecutarlo?
Traté de replicar su problema y me di cuenta de que no funciona porque los métodos de UtteranceProgressListener no se llaman en el hilo principal y es por eso que no se llama al método onBindViewHolder del adaptador.
Esto funcionó para mí y debería funcionar para usted también:
Use el método runOnUiThread{} para realizar acciones en RecyclerView como esta:
t1.setOnUtteranceProgressListener(object : UtteranceProgressListener() { override fun onError(utteranceId: String?) { } override fun onStart(utteranceId: String?) { runOnUiThread { recyclerView.adapter?.notifyItemChanged(position) } } override fun onStop(utteranceId: String?, interrupted: Boolean) { super.onStop(utteranceId, interrupted) onDone(utteranceId) } override fun onDone(utteranceId: String?) { val temp = position position = -1 runOnUiThread { recyclerView.adapter?.notifyItemChanged(temp) } } }Resolví el problema usando runOnUiThread gracias a Birju Vachhani .
Para obtener una demostración de trabajo completa no solo del problema que tuve, sino también de cómo expandir y colapsar correctamente las filas en un RecyclerView (sin eventos onClick en onBindViewHolder ), consulte mi Proyecto de demostración de Gitlab .