I want use 2-way dataBinding by LiveData. but change editText value not update textView that show user.name. what is wrong by my code? I use android studio 3.3 canary 3 and enable data binding v2 in gradle.properties by this code:
android.databinding.enableV2=true
model data class:
data class User(var name: String)
viewModel class:
class MainViewModel : ViewModel() {
val user = MutableLiveData<User>()
init {
user.value = User("ali")
}
}
mainActivity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val activityMainBinding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
activityMainBinding.setLifecycleOwner(this)
activityMainBinding.viewModel = viewModel
}
}
<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>
<variable
name="viewModel"
type="com.example.hoseinkelidari.databindingsample.MainViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="60dp"
android:layout_marginEnd="8dp"
android:text="@={viewModel.user.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@{viewModel.user.name}"
app:layout_constraintBottom_toTopOf="@+id/editText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Update: I found solution at this link:
LiveData update on object field change
I set this change and it work:
class User : BaseObservable() {
@get:Bindable
var firstName: String? = null
set(name) {
field = firstName
notifyPropertyChanged(BR.firstName)
}
}
class MainViewModel : ViewModel() {
var user = CustomMutableLiveData<User>()
init {
user.value = User()
}
}
and add new
class CustomMutableLiveData<T : BaseObservable> : MutableLiveData<T>() {
internal var callback: Observable.OnPropertyChangedCallback = object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable, propertyId: Int) {
//Trigger LiveData observer on change of any property in object
value = value
}
}
override fun setValue(value: T?) {
super.setValue(value)
//listen to property changes
value!!.addOnPropertyChangedCallback(callback)
}
}