如何重置LiveData<;布尔值>;当LiveData<;MVoice>;Android Studio中的双向数据绑定是否已更改?
在layout_detail.xml中,EditText使用双向数据绑定,按钮使用单向数据绑定 我希望在更改如何重置LiveData<;布尔值>;当LiveData<;MVoice>;Android Studio中的双向数据绑定是否已更改?,android,kotlin,android-databinding,android-livedata,Android,Kotlin,Android Databinding,Android Livedata,在layout_detail.xml中,EditText使用双向数据绑定,按钮使用单向数据绑定 我希望在更改aDetailViewModel.aMVoice.name时启用该按钮 当EditText的内容更改时,DetailViewModel中的aMVoice的值也将更改,我想我可以重置isChanged的值,但我不知道怎么做?你能告诉我吗 布局_detail.xml <layout xmlns:android="http://schemas.android.com/apk/re
aDetailViewModel.aMVoice.name
时启用该按钮
当EditText的内容更改时,DetailViewModel
中的aMVoice
的值也将更改,我想我可以重置isChanged
的值,但我不知道怎么做?你能告诉我吗
布局_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 = "",
)
class-DetailViewModel(private-val-mDBVoiceRepository:DBVoiceRepository,private-val-voiceId:Int):ViewModel(){
val aMVoice=mdbvoicepositionory.getVoiceById(voiceId)//我希望在aMVoice更改时重置isChanged
val isChanged:LiveData=MutableLiveData(false)
}
类DBVoiceRepository私有构造函数(私有val mDBVoiceDao:DBVoiceDao){
fun getVoiceById(id:Int)=mDBVoiceDao.getVoiceById(id)
}
@刀
接口DBVoiceDao{
@查询(“从voice_表中选择*,其中id=:id”)
趣味getVoiceById(id:Int):LiveData
}
@实体(tableName=“voice_table”,Index=[Index(“createdDate”))
数据类MVoice(
@PrimaryKey(autoGenerate=true)@ColumnInfo(name=“id”)变量id:Int=0,
变量名称:String=“”,
变量路径:String=“”,
)
像那样试试看
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: MutableLiveData<Boolean> = MutableLiveData<Boolean>(false)
fun listenChanges(owner: LifecycleOwner) {
aMVoice.observe(owner) {
isChanged.value?.apply {
isChanged.value = !this
}
}
}
}
当您想了解多个属性的值变化时,我们应该通过
map
转换在特定的LiveData
中分离每个属性。这些新的LiveData
s起着双向绑定的作用
最后,要集成更改,最好的方法是使用由每个更改触发的中介livedata
,然后检查值。因此,检查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)
)
}
要使用
map
转换,请不要忘记在build.gradle
中添加lifecycle livedata ktx
依赖项
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
谢谢但是你的代码不起作用
val-aMVoice=mdbvoicepositionory.getVoiceById(voiceId).map{isChanged.postValue(true);当aMVoice
的内容更改时,它}
将不会启动谢谢!但我想也许还有其他更好的方法。你知道我必须检查所有字段来定义它是否被更改,如果MVoice包括名称、路径、日期、描述、isFavorited等等,这是一项复杂的工作。不客气!我再次进行了更新,以满足检查更多属性的要求:)谢谢,但我认为您的代码无法运行,我无法理解什么是isChanged.value=!这意味着尝试一下——它可能需要一些定制。如果您不理解这部分代码,这意味着您并不真正了解Kotlin及其应用程序。此外,根据当前的执行线程,您可能需要使用isChanged.postValue(!this)。
<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}" />
// ...
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'