一、前言
DataBinding
是JetPack
的一部分,通常来说如果和JetPack
的其它部分结合使用效果会更好,这里对其进行记录。之前说过如果想要使数据改变的时候实时刷新到UI上面需要使用Observable
的子类才行,比如ObservableInt
。这里介绍一下如果和LiveData
、ViewMode
结合使用刷新UI的情况
二、LiveData的使用
这里实现一个功能,将LiveData
的数据绑定到UI上面,隔一段时间后更新该值,使其刷新UI
class UserViewModel: ViewModel() {
val userName = MutableLiveData<String>("默认值")
}
class MainActivity : AppCompatActivity() {
private val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
val viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
binding.viewmodel = viewModel
binding.lifecycleOwner = this
binding.root.postDelayed({
viewModel.userName.value = "更新值"
},1000)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewmodel"
type="com.example.myapplication.UserViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/update_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@{viewmodel.userName}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="value" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
三、ViewMode的使用
以下源自官方文档
您可以使用实现
Observable
的ViewModel
组件,向其他应用组件发出数据变化通知,这与使用LiveData
对象的方式类似。在某些情况下,您可能更愿意使用实现
Observable
接口的ViewModel
组件,而不是使用LiveData
对象,即使这样会失去对LiveData
的生命周期管理功能也不影响。使用实现Observable
的ViewModel
组件可让您更好地控制应用中的绑定适配器。例如,这种模式可让您更好地控制数据更改时发出的通知,您还可以指定自定义方法来设置双向数据绑定中的属性值。如需实现可观察的
ViewModel
组件,您必须创建一个从ViewModel
类继承而来并实现Observable
接口的类。您可以使用addOnPropertyChangedCallback()
和removeOnPropertyChangedCallback()
方法提供观察器订阅或取消订阅通知时的自定义逻辑。您还可以在notifyPropertyChanged()
方法中提供属性更改时运行的自定义逻辑。以下代码示例展示了如何实现一个可观察的ViewModel
:
该方式和自定义实现Observable
类的方式差不多,示例如下
ViewModel
class ObservableUserModel : ViewModel(), Observable {
private val callbacks: PropertyChangeRegistry = PropertyChangeRegistry()
@Bindable
var name = "默认值"
fun updateName(newName : String){
name = newName
notifyPropertyChanged(BR.name)
}
override fun addOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.add(callback)
}
override fun removeOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.remove(callback)
}
/**
* Notifies observers that all properties of this instance have changed.
*/
fun notifyChange() {
callbacks.notifyCallbacks(this, 0, null)
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes should be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
fun notifyPropertyChanged(fieldId: Int) {
callbacks.notifyCallbacks(this, fieldId, null)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="observableModel"
type="com.example.myapplication.ObservableUserModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/update_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@{observableModel.name}"
android:paddingStart="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="value" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
// Obtain ViewModel from ViewModelProviders
val viewModel = ViewModelProvider(this).get(ObservableUserModel::class.java)
binding.observableModel = viewModel
binding.root.postDelayed({
viewModel.updateName("新值--")
},1000)
}
}