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
相关产品推荐
相关产品推荐

