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