You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView集成TextToSpeech时语言支持标识始终为false如何解决

问题根本原因

TextToSpeech的初始化操作是异步执行的,你在onCreate中传入的初始化回调,执行时机晚于onViewCreated,所以你在onViewCreated中创建Adapter时,textToSpeechSupported还没被回调修改,始终是初始值false。

修复步骤

1. 修改Adapter,将支持标志改为可更新的可变变量

不要用private val接收不可变的布尔值,改成可修改的var,这样后续TTS初始化完成后可以直接更新Adapter内的标志值:

class WelcomeAdapter(
    private val textToSpeech: TextToSpeech, 
    // 去掉private修饰符,改为var方便外部更新状态
    var 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 {
                        // 弹出Toast提示语言不支持TTS
                    }
                }
            }
        }
    }
}

2. 在Fragment的TTS初始化回调中更新Adapter的标志位

TTS初始化完成拿到支持状态后,直接更新Adapter内的变量,如果你需要提前禁用/启用播报按钮,可以同步刷新列表:

class WelcomeFragment : Fragment() {

    private lateinit var welcomeAdapter: WelcomeAdapter
    private lateinit var textToSpeech: TextToSpeech

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        textToSpeech = TextToSpeech(requireContext()) { status ->
            if (status == TextToSpeech.SUCCESS) {
                val result = textToSpeech.setLanguage(Locale.getDefault())
                val isSupported = !(result == TextToSpeech.LANG_NOT_SUPPORTED || result == TextToSpeech.LANG_MISSING_DATA)
                // 初始化完成后更新Adapter内的标志位
                if (::welcomeAdapter.isInitialized) {
                    welcomeAdapter.textToSpeechSupported = isSupported
                    // 如果需要立刻更新列表项的按钮状态,打开下面的注释即可
                    // welcomeAdapter.notifyDataSetChanged()
                }
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 初始化Adapter时先传默认false,后续回调会更新状态
        welcomeAdapter = WelcomeAdapter(textToSpeech, false)
        binding.adapter = welcomeAdapter 
    }

    override fun onDestroy() {
        // 补充TTS资源释放逻辑,避免内存泄漏
        textToSpeech.stop()
        textToSpeech.shutdown()
        super.onDestroy()
    }
}

可选优化方案

如果你不想把Adapter的属性暴露成公开可变,也可以给Adapter加一个公开的更新方法,内部处理状态更新和列表刷新逻辑,封装性更好。

内容的提问来源于stack exchange,提问作者SVK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:24:04