Using DataBinding, I will write about the stumbling point and how to solve it. (Half is a memorandum) There are a lot of tips when creating a custom setter (BindingAdapter annotation).
When I made a custom setter in Java, I could write it like this.
@BindingAdapter("imageUrl")
public static void loadImage(ImageView view, String url) {
// do something
}
First, I wrote a custom setter in Kotlin:
class ImageViewBindingAdapter {
companion object {
@BindingAdapter("imageUrl")
@JvmStatic
fun loadImage(view: ImageView, imageUrl: String) {
// do something
}
}
}
DataBindingAttribute.Companion is not static and requires an object to use, retrieved from the DataBindingComponent.
The static method using companion object will result in the above error.
You can write a custom setter by the following method.
object ImageViewBindingAdapter {
@BindingAdapter("imageUrl")
@JvmStatic
fun loadImage(view: ImageView, imageUrl: String) {
// do something
}
}
You can also use Kotlin extension functions.
object ImageViewBindingAdapter {
@BindingAdapter("imageUrl")
@JvmStatic
fun ImageView.loadImage(imageUrl: String) {
// do something
}
}
XML is the same for both Java and Kotlin.
<ImageView
app:imageUrl="@{viewModel.imageUrl}" />
With Java, I could write like this.
@BindingAdapter({"imageUrl", "error"})
public static void loadImage(ImageView view, String url, Drawable error) {
// do something
}
This is the case with Kotlin.
object ImageViewBindingAdapter {
@BindingAdapter("imageUrl", "error")
@JvmStatic
fun ImageView.loadImage(imageUrl: String, error: Drawable) {
// do something
}
}
In XML, write:
<ImageView
app:imageUrl="@{viewModel.imageUrl}"
app:error="@{@drawable/errorImage}" />
As shown below, it does not work well if only some parameters are specified.
<ImageView
app:imageUrl="@{viewModel.imageUrl}" />
This is because the BindingAdapter's requireAll attribute defaults to true.
In this case, it will not be called unless all parameters are specified.
To make it called by some parameters, rewrite BindingAdapter as follows.
@BindingAdapter("imageUrl", "error", requireAll = false)
I wanted to set Int to BindingAdapter, so I wrote the following, but it didn't work.
object ImageViewBindingAdapter {
@BindingAdapter("imageUrl", "position")
@JvmStatic
fun ImageView.loadImage(imageUrl: String, position: Int) {
// do something
}
}
<ImageView
app:imageUrl="@{viewModel.imageUrl}"
app:position="1" />
The cause lies in the way it is written in XML, and it works if you change it as follows.
<ImageView
app:imageUrl="@{viewModel.imageUrl}"
app:position="@{1}" />
If you want to pass a Boolean, write:
<ImageView
app:imageUrl="@{viewModel.imageUrl}"
app:dispflag="@{true}" />
I don't know why I have to write this, so please let me know if anyone knows.
You can import the R class as follows.
<data>
<import type="com.sample.R"/>
<variable
name="viewModel"
type="com.sample.TestViewModel" />
</data>
<ImageView
app:src="@{viewModel.resourceId ?: R.drawable.error}" />
First, I checked if there was an Adapter provided as standard. https://android.googlesource.com/platform/frameworks/data-binding/+/master/extensions/baseAdapters/src/main/java/android/databinding/adapters
For example, if you want to use ʻandroid: onTextChanged of ʻEditTextView, [TextViewBindingAdapter.java](https://android.googlesource.com/platform/frameworks/data-binding/+/master/extensions/baseAdapters/src/ main / java / android / databinding / adapters / TextViewBindingAdapter.java) already has a BindingAdapter so you can use it.
There is also a description of BindingMethod here, so you may not need to bother to prepare a method BindingMethod like set ** Listener.
When I want to use a method that has Context as an argument in DataBinding, I referred to the following article.
Just pass it as context and it will work.
Handle method that passes context as argument in DataBinding
Recommended Posts