android - 如何在 Android Studio 中立即获取 LivaData<String> 的值?

标签 android android-livedata

savedRecordFileNameLivaData<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/

相关文章:

android - 无法在单元测试中访问 `Transformations.map` 中的值

android - 为什么 LiveData 有一个单独的 MutableLiveData 子类?

java - 将 LinearLayout 的方向作为参数发送给方法 - java Android Studio

java - setChecked 不适用于单选按钮 android?

html - 如何使用android向webview显示html内容

java - Android viewholder 类范围广

android - 为什么我无法在 lambda 函数下调用 kotlin 挂起函数

java - 使用实时数据和改造 Android 时图像无法正确显示

android - 将 ArrayAdapter 与 LiveData 结合使用。

android - 使用静态字段创建 Singleton 类以在 Android 中的 Activity 之间进行通信是否有任何缺点?