8

I used to create DataBindingAdapter for creating custom xml attributes in data binding.

object DataBindingAdapter {
    @BindingAdapter("android:src")
    fun setImageByRes(imageView: ImageView, @DrawableRes resId: Int) {
        imageView.setImageResource(resId)
    }
}

It was working well in Java. But not working in kotlin.

As I understand object in kotlin are similer to static method of Java. But its not working in data binding.

java.lang.IllegalStateException: Required DataBindingComponent is null in class FragmentBottomBarBinding. A BindingAdapter in acr.browser.lightning.utils.DataBindingAdapter is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.

Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212

2 Answers2

26

Just add the @Jvmstatic annotation on setImageByRes method.

object DataBindingAdapter {
    @BindingAdapter("android:src")
    @JvmStatic
    fun setImageByRes(imageView: ImageView, @DrawableRes resId: Int) {
        imageView.setImageResource(resId)
    }
}

as per the @Jvmstatic doc

Specifies that an additional static method needs to be generated from this element if it's a function. If this element is a property, additional static getter/setter methods should be generated.

In short method declared in one place and used from multiple languages of JVM. If you're calling a method from Java, then you should declare it as @JvmStatic, because adding the @JvmStatic annotation in one place will allow you to leave out multiple .Companion references in multiple places.

Moinkhan
  • 12,732
  • 5
  • 48
  • 65
7

No. Object in kotlin is same like singleton. I think u dont need put it in Object. Just make new file lets say BindingAdapters.kt and u dont need write any class or object keywords.

It should look like this. Nothing else. If u need more functions just add it below this one. Again no class keyword or brackets are needed. It will be global function. Maybe u should also use ContextCompat for getting resource properly with context from imageView. And i would rather name it differently than android:src. What about imageResBinder

@BindingAdapter("imageResBinder")
fun setImageByRes(imageView: ImageView, @DrawableRes resId: Int) {
    imageView.setImageResource(resId)
}

and after that in your .xml file

<android.support.v7.widget.AppCompatImageView
    style="@style/Image.SomeImageStyle"
    app:imageResBinder="@{viewModel.getImageRes()}" />
Kebab Krabby
  • 1,574
  • 13
  • 21
  • If I need, How can I call this function from another kotlin? – Khemraj Sharma Aug 16 '18 at 11:34
  • U cant. Only thing u can is to call it from different .xml file because its global method only for databinding. So u cant lets say call it in fragment onViewCreated(). Of course u can make a static class for loading resources but i think u should not if u are using databinding. U can also put this bindingAdapter only into some model class: https://stackoverflow.com/questions/40845767/where-to-place-android-bindingadapter-method – Kebab Krabby Aug 16 '18 at 11:38
  • Then I will prefer @JvmStatic because there can be some common function which can be useful to call from another activity also. – Khemraj Sharma Aug 16 '18 at 11:40