如何解决在Android Studio中的双向数据绑定中更改LiveData <MVoice>时,如何重置LiveData <Boolean>?
EditText 使用双向数据绑定,而 Button 使用 layout_detail.xml
中的单向数据绑定我希望在更改aDetailViewModel.aMVoice.name
时启用按钮。
当EditText的内容更改时,aMVoice
中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
转换将每个属性分开在特定的map
中。这些新的LiveData
起到双向绑定的作用。
最后,要集成更改,最好的方法是使用MediatorLiveData
由每个更改触发,然后检查值。因此,足以检查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
, etc :
<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'
,
那样尝试
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
}
}
}
}
并从您有lifecycle owner的位置呼叫监听器-例如来自Fragment
class Fragment1 : Fragment() {
lateinit var viewModel: DetailViewModel
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
viewModel.listenChanges(viewLifecycleOwner)
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。