在HiltViewModel中获取Application/上下文调用谷歌语音转文字API
在Hilt ViewModel中获取Application实例的解决方法
核心方案:通过Hilt构造注入Application
Hilt默认支持Application类型的依赖注入,直接在@HiltViewModel的构造函数中声明Application参数即可获取实例,无需额外配置。
代码修改步骤
- 在ViewModel构造函数中添加
Application参数并注入:
@HiltViewModel class SettingsViewModel @Inject constructor( private val settingsRepository: SettingsRepository, private val application: Application // 新增:注入Application ) : ViewModel(), RecognitionListener
- 替换代码中所有需要上下文的地方:
- 创建
SpeechRecognizer时直接使用application(Application本身就是Context的子类) - 获取包名时用
application.packageName
修改后的完整代码示例
@HiltViewModel class SettingsViewModel @Inject constructor( private val settingsRepository: SettingsRepository, private val application: Application // 注入Application ) : ViewModel(), RecognitionListener { data class SpeechState( val spokenText: String = "", val error: String = "" ) private val _settings = MutableStateFlow(value = Settings()) val settings: StateFlow<HomeSettings> = _settings.asStateFlow() private val speechState = MutableStateFlow(value = SpeechState()) // 用lazy延迟初始化,避免ViewModel创建时就持有SpeechRecognizer(优化内存) private val speechRecognizer: SpeechRecognizer by lazy { SpeechRecognizer.createSpeechRecognizer(application).apply { setRecognitionListener(this@SettingsViewModel) } } private fun updateResults(speechBundle: Bundle?) { val userSaid = speechBundle?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) speechState.value = speechState.value.copy(spokenText = userSaid?.get(0) ?: "") reactToSpeech(speechState.value.spokenText) } override fun onEndOfSpeech() = speechRecognizer.stopListening() override fun onResults(results: Bundle?) = updateResults(speechBundle = results) override fun onPartialResults(results: Bundle?) = updateResults(speechBundle = results) override fun onError(errorCode: Int) {} private val recognizerIntent: Intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, application.packageName) putExtra( RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH ) putExtra(RecognizerIntent.EXTRA_PROMPT, "Talk") //putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true) } fun startListening(){ speechRecognizer.startListening(recognizerIntent) } private fun reactToSpeech(speech: String){ when(speech){ "run" -> Log.w("App", "Running!") "stop" -> Log.w("App", "Stopped!") else -> {} } } override fun onReadyForSpeech(p0: Bundle?) {} override fun onBeginningOfSpeech() {} override fun onRmsChanged(p0: Float) {} override fun onBufferReceived(p0: ByteArray?) {} override fun onEvent(p0: Int, p1: Bundle?) {} }
额外优化提示
- 用
lazy延迟初始化SpeechRecognizer,避免ViewModel初始化时就持有该对象,减少内存占用风险 - 注意在ViewModel销毁时(重写
onCleared()方法)调用speechRecognizer.destroy(),防止内存泄漏
内容的提问来源于stack exchange,提问作者Alix Blaine
相关产品推荐
相关产品推荐

