I am trying to learn data binding with Kotlin and I was able to implement it successfully for edit text and text views. After that I am trying to use it for Image Views. I am currently trying to give an option to users to choose their profile picture by clicking on the imageview. This code works properly but when I try to set the image to the view using data binding adapter , I get the following error.
Found data binding errors. ****/ data binding error ****msg:Cannot find the getter for attribute 'android:userImage' with value type java.lang.String on de.hdodenhof.circleimageview.CircleImageView. file:/home/parangat-pt-p10/AndroidStudioProjects/ReUsableAndroid/reusable_android/app/src/main/res/layout/activity_signup.xml loc:25:12 - 31:48 ****\ data binding error ****
Below is my code for the same.
Layout code of ImageView
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:userImage="@{signup.userImage}"
android:id="@+id/iv_user"
android:src="@drawable/profile"/>
Model class code
class Signup {
var userImage=""
var firstName=""
var lastName=""
var phoneNumber=""
var postCode=""
var country=""
var email=""
var password=""
var confirmPassword=""
var isAcceptTerms=false
@BindingAdapter("android:userImage")
fun loadImage(view: CircleImageView, imageUrl: String) {
userImage=imageUrl
Glide.with(view.context).load(imageUrl).into(view)
}
}
And this is what I am doing after user selected image
override fun onSingleImageSelected(uri: Uri?) {
signupBinding.signup?.loadImage(iv_user,uri.toString())
}
Since this is written in kotlin, therefore there is no need to define the getter and setter methods but the error states that no getter method found.
As suggested by Enzokie, I created the binding Adapter in separate file like below
@BindingAdapter("userImage")
fun loadImage(view: CircleImageView, imageUrl: String) {
Glide.with(view.context).load(imageUrl).into(view)
}
But I still have the same issue.
android:src
) for whole app.android:src
instead of android:userImage
.CircleImageView
in BindingAdapter
, make common adapter with ImageView
because CircleImageView
is child of ImageView
.signup.userImage = "someUrl"
then use Bindable
and notify
, other wise no need of both.ObservableField
instead of extending BaseObservable
class, then you don't need to use Bindable
and notify
.Signup.class
class Signup : BaseObservable() {
@get:Bindable
var userImage: String = ""
set(value) {
field = value
notifyPropertyChanged(BR.userImage)
}
}
DataBindingAdapter.kt
// binding adapter for setting url/uri on ImageView
@BindingAdapter("android:src")
fun setImageUrl(view: ImageView, url: String) {
Glide.with(view.context).load(url).into(view)
}
layout.xml
<de.hdodenhof.circleimageview.CircleImageView
...
android:src="@{signup.userImage}"/>
Now you can set binding.signup.userImage = "Url"
, it will refract on UI automatically.
When you use data binding, and you want UI automatic update after setting fields. then your model should be one of below :
In your case, initially your URL is empty (""). Now when you set image after some time programmatically, then UI is not notified because you are not using any observing option like I said above.
The difference between both is, Live data is Android Lifecycle Aware (Activity/ Fragments/ Services).
LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.