How to databinding image loading with Glide?

You need to make url parameter nullable, and guard against null like this:

@BindingAdapter("imageUrl")
fun loadImage(view: RoundedImageView, url: String?) {
    if (!url.isNullOrEmpty()) {
        .....
    }
}

It would be more convenient to create a binding adapter which accepts multiple optional attributes so you can customize the loading request. Here's an example of such adapter.

@BindingAdapter(
  "srcUrl",
  "circleCrop",
  "placeholder",
  requireAll = false // make the attributes optional
)
fun ImageView.bindSrcUrl(
  url: String,
  circleCrop: Boolean = false,
  placeholder: Drawable?,
) = Glide.with(this).load(url).let { request ->

  if (circleCrop) {
    request.circleCrop()
  }

  if (placeholder != null) {
    request.placeholder(placeholder)
  }

  request.into(this)
}

And you can use it like this:

<ImageView
  ...
  app:srcUrl="@{someUrl}"
  app:placeholder="@{@drawable/ic_placeholder}"
  app:circleCrop="@{true}" />

You can also find an example in sources of the Owl - an official Android sample app on GitHub. See BindingAdapters.kt.


BindingAdapter methods should be static, so marking it @JvmStatic would help in this case.

But that will generate 'compile time error' that "methods can't be static inside class" and so it should be moved to companion object or named objects.

In your case, you're having method in class member level so moving it to companion object will help. So for MyItemViewModel.kt make companion object and move method there like below :

class MyItemViewModel{
    //Some code
    companion object {

        @JvmStatic
        @BindingAdapter("imageUrl")
        fun loadImage(view: RoundedImageView, url: String) { // This methods should not have any return type, = declaration would make it return that object declaration.
            Glide.with(view.context).load(url).into(view)
        }
    }
    //Some other code
}

Note: Also remove method declaration with =. Binding methods should have return type Unit.


Edit: One can also use method Glide.with(view) as @hmac suggested in comment, but ...

Things to consider before using this Glide.with(view):

  1. Your view should be attached before using it from Activity/Fragment. Best usecase for this method is Custom View/ViewGroup.

  2. Consider layout hierarchy before using this method as too many nested/large hierarchy layouts are discouraged to use that method. It becomes inefficient for such layouts.

  3. Also note that, if view is inside non-support fragment class or context is of non-support fragment than that can produce noisy log as documentation indicates, first migrate to support library (Now considered as AndroidX) instead before using this method!


This work fine for me

             <ImageView
                    android:layout_width="0dp"
                    android:layout_height="100dp"
                    android:layout_margin="10dp"
                    android:layout_gravity="center"
                    bind:image="@{subcategory.image}"
                    bind:placeholder="@{@drawable/no_imge}"
                    android:layout_weight="1" />




  @BindingAdapter("image","placeholder")
    fun setImage(image: ImageView, url: String?, placeHolder: Drawable) {

        if (!imageUrl.isNullOrEmpty()){

          Glide.with(image.context).load(url).centerCrop()
       .placeholder(R.drawable.no_imge)
                    .into(image)
        }
        else{
            image.setImageDrawable(placeHolder)
        }


    }