9

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.

5
  • 4
    have you tried @JvmStatic annotation on setImageByRes.
    – Moinkhan
    Commented Aug 16, 2018 at 11:23
  • If you're facing interop problems (Java calling Kotlin code), a good approach is to decompile the generated bytecode to Java and see how the result looks. This often makes it immediately clear where the interface mismatches. Commented Aug 16, 2018 at 11:27
  • @Moinkhan JvmStatic did the trick. Commented Aug 16, 2018 at 11:29
  • You forgot @JvmStatic Commented Aug 16, 2018 at 11:33
  • Because you did not answer, so I did your work. You can now answer. I will mark it right, You deserve it. Commented Aug 16, 2018 at 12:09

3 Answers 3

27

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.

2
  • If you add a little info about JvmStatic for new comers, that will be great. Commented Aug 16, 2018 at 12:13
  • Hi @Moinkhan how to link this DataBindingAdapter with recycler view or adapter ? Commented Sep 25, 2020 at 14:25
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()}" />
3
  • If I need, How can I call this function from another kotlin? Commented Aug 16, 2018 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: stackoverflow.com/questions/40845767/… Commented Aug 16, 2018 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. Commented Aug 16, 2018 at 11:40
0

in my case the reason was that I should have put the DataBinding setter method outside of the class

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.