使用 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 的选定项目?

如何使用 Recycler View 的长按位置获取 SQLite 列值?

Recycler View 和 DialogFragment 苦苦挣扎(Kotlin)

如何在 kotlin 的 Recycler View Adapter 中添加更多数据列表而不清除先前的数据?

在使用 Recycler View 时尝试在空对象引用上调用虚拟方法