【问题标题】:notifyItemChanged() not working when called within setOnUtteranceProgressListener在 setOnUtteranceProgressListener 中调用 notifyItemChanged() 时不起作用
【发布时间】:2019-07-30 09:35:18
【问题描述】:

编辑

我在Github 上创建了一个演示项目,显示了确切的问题。 Git Project.


我在Kotlin 中写了一个可扩展的recyclerView 每一行都有一个使用TextToSpeech 的播放按钮。播放按钮的文本应在播放时更改为停止,然后在播放结束后更改回播放。

当我在setOnUtteranceProgressListeneronStartonDone 中调用notifyItemChanged 时,不会调用onBindViewHolder,并且recyclerView 中的行将不再正确展开和折叠。

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

如何从setOnUtteranceProgressListener 中调用notifyItemChanged(position),或者我可以使用什么回调,以便 notifyItemChanged 仅在可以安全执行时执行?

【问题讨论】:

  • Values.position 是静态对象中的变量。我使用它是因为我将setOnUtteranceProgressListeneradapter 移动到fragment 以查看是否可以解决问题。我没有手动创建任何新线程,但似乎问题仍然与线程安全有关,因为从setOnUtteranceProgressListener 中调用notifyItemChanged 显然不安全。我已经确认 onStartonDone 被正确调用。
  • @acarlstein 文本已显示,因此聋人可以只阅读文本,但他们可能需要单击该行以展开并查看整个文本。

标签: java android kotlin android-recyclerview


【解决方案1】:

我试图复制您的问题,但我知道它不起作用,因为在主线程上未调用 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)
        }
    }
}

【讨论】:

    【解决方案2】:

    感谢Birju Vachhani,我使用runOnUiThread 解决了这个问题。

    有关我遇到的问题以及如何正确展开和折叠 RecyclerView 中的行(onBindViewHolder 中没有 onClick 事件)的完整工作演示,请参阅我的 Gitlab Demo Project

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 2017-07-23
      • 1970-01-01
      相关资源
      最近更新 更多