使用 Recycler View 时如何在 Text To Speech 中实现错误处理
Posted
技术标签:
【中文标题】使用 Recycler View 时如何在 Text To Speech 中实现错误处理【英文标题】:How to Implement Error handling in Text To Speech while working with Recycler View 【发布时间】:2021-12-26 00:18:11 【问题描述】:我将 TextToSpeech
从 Fragment 传递到我的 RecyclerView 适配器。
在传递的同时,我还发送了一个标志textToSpeechSupported
,以确认TextToSpeech
公告是否支持当前设置的设备语言。
但是每次这个标志的值被设置为false
,即使我在onCreate
中将值设置为true
。
我的实现方法似乎有问题。
但我厌倦了调试并添加了日志。
我还进行了多次测试并尝试了各种其他组合。但是每次传递标志textToSpeechSupported
的值都是false
,即使语言受支持。
我在这里错过了什么吗?
如果TextToSpeech
支持设备语言,我需要将标志textToSpeechSupported
的值设为true
请指导。
class WelcomeFragment : Fragment()
private lateinit var welcomeAdapter: WelcomeAdapter
private lateinit var textToSpeech: TextToSpeech
private var textToSpeechSupported: Boolean = false
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
textToSpeech = TextToSpeech(requireContext()) status ->
if (status == SUCCESS)
val result = textToSpeech.setLanguage(Locale.getDefault())
textToSpeechSupported =
!(result == TextToSpeech.LANG_NOT_SUPPORTED || result == TextToSpeech.LANG_MISSING_DATA)
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
super.onViewCreated(view, savedInstanceState)
welcomeAdapter = WelcomeAdapter(textToSpeech, textToSpeechSupported)
binding.adapter = welcomeAdapter
class Welcomedapter(private val textToSpeech: TextToSpeech, private val textToSpeechSupported: Boolean) : ListAdapter<Welcome, ViewHolder>(WelcomeDiffCallback())
//....
class ViewHolder private constructor(val binding: ContainerWelcomeBinding) : RecyclerView.ViewHolder(binding.root)
fun bind(item: Welcome, textToSpeech: TextToSpeech, textToSpeechSupported: Boolean)
binding.apply
welcomeMessageText.text = item.welcome
textToSpeechImage.setOnClickListener
if (textToSpeechSupported)
textToSpeech.speak(item.welcome, TextToSpeech.QUEUE_FLUSH, null)
else
// Send an event for Toast saying that language is not supported for Text to Speech
目的/目的是确保正确计算标志textToSpeechSupported
的值并将其传递给Recycler View Adapter。
【问题讨论】:
【参考方案1】:问题是 onViewCreated 在 tts 有时间初始化之前被调用,所以你太早访问 textToSpeechSupported 并且你总是得到你的默认 (false) 值。
所以,不要调用:
welcomeAdapter = WelcomeAdapter(textToSpeech, textToSpeechSupported)
binding.adapter = welcomeAdapter
从 onViewCreated 内部,创建一个新函数:
fun thisFunctionRunsAFTERtheTTSisInitialized()
// put that code here instead.
然后从 onCreate 内部调用该函数,以便在 tts 初始化后运行:
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
textToSpeech = TextToSpeech(requireContext()) status ->
if (status == SUCCESS)
val result = textToSpeech.setLanguage(Locale.getDefault())
textToSpeechSupported =
!(result == TextToSpeech.LANG_NOT_SUPPORTED || result == TextToSpeech.LANG_MISSING_DATA)
thisFunctionRunsAFTERtheTTSisInitialized() // <---------------
【讨论】:
谢谢。 (第 1 点)请注意,如果我将函数thisFunctionRunsAFTERtheTTSisInitialized()
保留在 if statement
中,那么它只会在 textToSpeech
状态为 SUCCESS
时执行,如果状态不同,那么我们的 welcomeAdapter
将永远不会执行初始化。 (第2点)可以将回收器视图适配器初始化放在OnCreate
中还是应该将其保留在onCreateView
中
第 1 点,你是对的。不好意思我不知道第2点的答案,我的答案主要是为了说明tts初始化是异步和延迟的。我建议单独发布任何新问题,如果您这样做,请包括所有代码,包括包含该片段的活动。解决问题的方法可能完全不同。【参考方案2】:
最好将接口或函数传递给适配器 例如
class Welcomedapter(private val block : () -> Unit) : ListAdapter<Welcome, ViewHolder>(WelcomeDiffCallback())
//....
class ViewHolder private constructor(val binding: ContainerWelcomeBinding) : RecyclerView.ViewHolder(binding.root)
fun bind(item: Welcome, textToSpeech: TextToSpeech, textToSpeechSupported: Boolean)
binding.apply
welcomeMessageText.text = item.welcome
textToSpeechImage.setOnClickListener
block()
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
super.onViewCreated(view, savedInstanceState)
welcomeAdapter = WelcomeAdapter
if (textToSpeechSupported)
textToSpeech.speak(item.welcome, TextToSpeech.QUEUE_FLUSH, null)
else
// show the toast here now
binding.adapter = welcomeAdapter
【讨论】:
以上是关于使用 Recycler View 时如何在 Text To Speech 中实现错误处理的主要内容,如果未能解决你的问题,请参考以下文章
如何使 Recycler View 表现得像 PlayStore Recycler Views
如何使用 Recycler View 的长按位置获取 SQLite 列值?
Recycler View 和 DialogFragment 苦苦挣扎(Kotlin)