savedRecordFileName
是 LivaData<String>
的变量,希望得到savedRecordFileName
的值在代码 A 中立即执行。
你知道LiveData变量是惰性变量,可能是savedRecordFileName
的值binding.btnStop.setOnClickListener { }
中为空,所以 binding.btnStop.setOnClickListener { }
中的代码当 savedRecordFileName
的值时不会被触发为空。
我希望binding.btnStop.setOnClickListener { }
中的代码总是会被解雇,我该怎么办?
顺便说一句,我认为代码 B 不合适,因为 savedRecordFileName
的值可能会被其他功能改变。
代码B
binding.btnStop.setOnClickListener {
mHomeViewModel.savedRecordFileName.observe(viewLifecycleOwner){
val aMVoice = getDefaultMVoice(mContext,it)
mHomeViewModel.add(aMVoice)
}
}
代码A
class FragmentHome : Fragment() {
private val mHomeViewModel by lazy {
getViewModel {
HomeViewModel(mActivity.application, provideRepository(mContext))
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...
binding.btnStop.setOnClickListener {
mHomeViewModel.savedRecordFileName.value?.let{
val aMVoice = getDefaultMVoice(mContext,it)
mHomeViewModel.add(aMVoice)
}
}
...
return binding.root
}
}
class HomeViewModel(val mApplication: Application, private val mDBVoiceRepository: DBVoiceRepository) : AndroidViewModel(mApplication) {
val savedRecordFileName: LiveData<String> = mDBVoiceRepository.getTotalOfVoice().map {
mApplication.getString(R.string.defaultName, (it+1).toString())
}
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
fun getTotalOfVoice() = mDBVoiceDao.getTotalOfVoice()
}
@Dao
interface DBVoiceDao{
@Query("SELECT count(id) FROM voice_table")
fun getTotalOfVoice(): LiveData<Long>
}
添加内容
致里德库利:谢谢!
我认为你的方式“将所有内容移动到 viewmodel 类中”很好!
我认为即使 filename
也没关系。 livedata 在你的代码 C 中,对吗?
代码C
viewModelScope.launch(Dispatchers.IO) {
filename = dao.getFilename() // without livedata. I think it will be OK even if the filename is livedata
voice = getDefaultVoice(...) // also do this in background
add(voice)
result.postValue(true)
}
最佳答案
正如您所说,您应该在后台进行 Room 查询,以避免阻塞 ui 线程。但你不应该就此止步。在后台线程中做尽可能多的工作。在您的情况下,单击按钮时,开始运行一个后台线程来完成所有工作:从数据库获取名称(通过直接查询,现在可以在后台运行),获取默认语音并将其添加到无论您将其添加到什么内容。
您还应该将所有这些移到 View 模型类中。
btnStop.setOnClickListener {
viewmodel.stop()
}
在 View 模型中是这样的(java/伪代码):
void stop() {
runinbackgroundthread {
filename = dao.getFilename() // without livedata
voice = getDefaultVoice(...) // also do this in background
add(voice)
// If you want the action to have a reault, observable by ui
// use a MutableLiveData and set it here, via postValue()
// as we are still in background thread.
result.postValue(true)
}
}
关于如何实际实现我的伪代码runinbackgroundthread
,请参阅此处的一些官方指南:https://developer.android.com/guide/background/threading
简而言之,对于 Kotlin 协程,它应该像这样:
viewModelScope.launch(Dispatchers.IO) {
filename = dao.getFilename() // without livedata
voice = getDefaultVoice(...) // also do this in background
add(voice)
result.postValue(true)
}
关于android - 如何在 Android Studio 中立即获取 LivaData<String> 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64474976/