I am passing TextToSpeech
from Fragment to my RecyclerView Adapter.
While passing it, I am also sending a flag textToSpeechSupported
to confirm whether the currently set device language is supported for TextToSpeech
announcement or not.
But every time the value of this flag is being set as false
, even though I am setting the value to true
in onCreate
.
It seems there is an issue with my implementation approach.
But I tired to debug and also added Logs.
Also I did multiple test and tried various other combinations. But every time the flag textToSpeechSupported
value is being passed is false
, even if the language is supported.
Am I missing something here.
I need the flag textToSpeechSupported
value to be true
if the device language is supported by TextToSpeech
Please guide.
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
}
}
}
}
}
}
The objective/goal is to ensure that value of flag textToSpeechSupported
is correctly calculated and passed to Recycler View Adapter.
CodePudding user response:
The problem is that onViewCreated is being called BEFORE the tts has had time to initialize, so you are accessing textToSpeechSupported too early and you're always getting your default (false) value.
So, instead of calling:
welcomeAdapter = WelcomeAdapter(textToSpeech, textToSpeechSupported)
binding.adapter = welcomeAdapter
from inside onViewCreated, make a new function:
fun thisFunctionRunsAFTERtheTTSisInitialized() {
// put that code here instead.
}
And then call that function from inside your onCreate so it will run AFTER the tts has initialized:
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() // <---------------
}
}
}
CodePudding user response:
It would be better to pass an interface or function to adapter e.g
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
}