android - 如何重置 LiveData当 LiveData在 Android Studio 中的双向数据绑定中更改了吗?
问题描述
在layout_detail.xml中EditText使用双向数据绑定和Button使用单向数据绑定
我希望Button将在aDetailViewModel.aMVoice.name
更改时启用。
当 EditText 的内容改变时,aMVoice
in的值DetailViewModel
也会改变,我想我可以重新设置 的值isChanged
,但我不知道该怎么办?你能不能告诉我?
layout_detail.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable name="aDetailViewModel"
type="info.dodata.voicerecorder.viewcontrol.DetailViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/eTName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="@={aDetailViewModel.aMVoice.name}" />
<Button
android:id="@+id/btnSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="@{aDetailViewModel.isChanged}"
android:text="Save" />
</LinearLayout>
</layout>
代码
class DetailViewModel(private val mDBVoiceRepository: DBVoiceRepository, private val voiceId:Int) : ViewModel() {
val aMVoice=mDBVoiceRepository.getVoiceById(voiceId) //I hope to reset isChanged when aMVoice is changed
val isChanged: LiveData<Boolean> = MutableLiveData<Boolean>(false)
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
fun getVoiceById(id:Int)=mDBVoiceDao.getVoiceById(id)
}
@Dao
interface DBVoiceDao{
@Query("SELECT * FROM voice_table where id=:id")
fun getVoiceById(id:Int):LiveData<MVoice>
}
@Entity(tableName = "voice_table", indices = [Index("createdDate")])
data class MVoice(
@PrimaryKey (autoGenerate = true) @ColumnInfo(name = "id") var id: Int = 0,
var name: String = "",
var path: String = "",
)
解决方案
当您想找出多个属性的值变化时,我们应该在特定的LiveData
viamap
转换中将每个属性分开。这些LiveData
news起到双向绑定的作用。
最后,要集成更改,最好的方法是使用 aMediatorLiveData
被每个更改触发,然后检查值。DB
因此,检查初始值与从视图中接收到的值是否相等就足够了。
class DetailViewModel(...) {
private val aMVoice = mDBVoiceRepository.getVoiceById(voiceId)
val voiceName = aMVoice.map { it.name } as MutableLiveData<String>
val voicePath = aMVoice.map { it.path } as MutableLiveData<String>
// ... (similar for more attributes)
val isChanged = MediatorLiveData<Boolean>().apply {
addSource(voiceName) { postValue(currentMVoice != aMVoice.value) }
addSource(voicePath) { postValue(currentMVoice != aMVoice.value) }
// ... (similar for more attributes)
}
// it collects current values delivered from views as a `MVoice` object.
private val currentMVoice: MVoice?
get() = aMVoice.value?.copy(
name = voiceName.value ?: "",
path = voicePath.value ?: "",
// ... (similar for more attributes)
)
}
然后在布局中使用voiceName
,voicePath
等:
<EditText
android:id="@+id/eTName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="@={aDetailViewModel.voiceName}" />
<EditText
android:id="@+id/eTPath"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="text"
android:text="@={aDetailViewModel.voicePath}" />
// ...
要使用map
转换,请不要忘记添加lifecycle-livedata-ktx
依赖项,build.gradle
如果您以前没有的话。
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
推荐阅读
- ios - SocketRocket 库订阅主题 ios
- apache-camel - 开发 Apache camel 应用程序并在 Karaf 上运行
- batch-file - 嵌套用于批量执行两次
- java - 使用 Hibernate 更新 HSQLDB 上的 LOB/BLOB 值会产生数据异常
- r - 使用 summarise_all 折叠多个字符列会引发错误或包含 NA
- linux - 如何在 nohup 模式下解压文件
- json - “Book []”类型上不存在属性“ResultJson”
- ruby - 如何拆分 Ruby 哈希数组
- android - 将位图保存到 SD 卡不创建任何文件
- c++ - 使用 new 运算符初始化指向 const float 等的指针的指针