notifyItemChanged () не работает при вызове внутри setOnUtteranceProgressListener - PullRequest
3 голосов
/ 08 марта 2019

Редактировать

Я создал демонстрационный проект на Github, показывающий точную проблему. Git Project .


Я написал расширяемый recyclerView в Kotlin В каждой строке есть кнопка воспроизведения, которая использует TextToSpeech. Текст кнопки воспроизведения должен измениться, чтобы остановить ее во время воспроизведения, а затем вернуться к воспроизведению после ее завершения.

Когда я вызываю notifyItemChanged в пределах onStart и onDone из setOnUtteranceProgressListener, onBindViewHolder не вызывается, и строки в представлении recycler больше не будут расширяться и сворачиваться правильно.

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)
//                    }
        })
    }
})

onBindViewHolder:

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)
    }
}

Как я могу вызвать notifyItemChanged(position) из setOnUtteranceProgressListener или какой обратный вызов я могу использовать, чтобы notifyItemChanged выполнялся только тогда, когда это безопасно для выполнения?

Ответы [ 2 ]

4 голосов
/ 11 марта 2019

Я попытался повторить вашу проблему и узнал, что она не работает, потому что методы UtteranceProgressListener не вызываются в основном потоке, и поэтому onBindViewHolder метод адаптера не вызывается.

Это сработало и должно работать для вас тоже:

Используйте метод runOnUiThread{} для выполнения действий с RecyclerView следующим образом:

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)
        }
    }
}
0 голосов
/ 12 марта 2019

Я решил проблему, используя runOnUiThread благодаря Бирю Вачхани .

Для полной рабочей демонстрации не только проблемы, с которой я столкнулся, но и того, как правильно развернуть и свернуть строки вRecyclerView (нет onClick событий в onBindViewHolder), см. мой демонстрационный проект Gitlab .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...