如何使用 Glide 加载数据绑定图像?

How to databinding image loading with Glide?

我正在尝试使用数据绑定加载图像。但我从来没有克服它。我的问题在哪里?下面是我的代码和布局构造。

MyItemViewModel.kt

  @BindingAdapter("imageUrl")
    fun loadImage(view: RoundedImageView, url: String) = Glide.with(view.context).load(url).into(view)

layout.xml

<data>

    <variable
            name="viewModel"
            type="com.myapp.app.ui.activity.albumlist.AlbumItemViewModel"/>
</data>

  <com.makeramen.roundedimageview.RoundedImageView
                android:layout_width="60dp"
                android:id="@+id/ivRoundedAlbum"
                android:layout_marginStart="@dimen/unit_20_dp"
                app:riv_corner_radius="8dp"
                app:imageUrl="@{viewModel.data.cover}"
                android:layout_height="60dp"/>

我认为最好的做法应该是在 layout.xml 中为字符串类型的 imageUrl 创建一个单独的变量。 BindingAdapter 应该在模型 class 中。此外,BindingAdapter 方法应该是静态的,如注释中所指出的那样。您可以通过使用 @JvmStatic 注释包装在伴生对象中来实现。有关详细信息,请查看 this

    <variable
        name="imageUrl"
        type="String" />

BindingAdapter 方法应该是 static,因此在这种情况下将其标记为 @JvmStatic 会有所帮助。

但这会生成 'compile time error'"methods can't be static inside class" 所以它应该移动到 伴随对象命名对象.

在您的情况下,您在 class 成员级别 中有方法,因此将其移动到 伴随对象 会有所帮助.因此,对于 MyItemViewModel.kt 创建伴随对象并在那里移动方法,如下所示:

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.


编辑: 也可以按照@hmac 在评论中的建议使用方法 Glide.with(view),但是 ...

使用此之前需要考虑的事项 Glide.with(view):

  1. 在使用 Activity/Fragment 之前,应附加您的视图。此方法的最佳用例是 Custom View/ViewGroup.

  2. 在使用此方法之前考虑布局层次结构,因为不鼓励太多 nested/large 层次结构布局使用该方法。这样的布局会变得低效。

  3. 另请注意,如果视图位于 non-support 片段 class 内或上下文属于 non-support 片段,那么会产生嘈杂的日志,如 documentation 表示,先迁移到支持库(现在被认为是AndroidX),然后再使用此方法!

您需要使 url 参数可为空,并像这样防止空值:

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

这对我来说很好

             <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)
        }


    }

像这样使用app:glideSrc

           <ImageView
                android:id="@+id/sender_profile_image_view"
                android:layout_width="@dimen/email_sender_profile_image_size"
                android:layout_height="@dimen/email_sender_profile_image_size"
                android:contentDescription="@string/email_sender_profile_content_desc"
                android:scaleType="centerCrop"
                app:glideCircularCrop="@{true}"
                app:glideSrc="@{email.sender.avatar}"
                app:layout_constraintTop_toTopOf="@id/sender_text_view"
                app:layout_constraintBottom_toBottomOf="@+id/recipient_text_view"
                app:layout_constraintEnd_toEndOf="parent"
                tools:src="@drawable/avatar_3" />

并在 BindingAdapter

@BindingAdapter(
  "glideSrc",
  "glideCenterCrop",
  "glideCircularCrop",
  requireAll = false
)
fun ImageView.bindGlideSrc(
  @DrawableRes drawableRes: Int?,
  centerCrop: Boolean = false,
  circularCrop: Boolean = false
) {
  if (drawableRes == null) return

  createGlideRequest(
    context,
    drawableRes,
    centerCrop,
    circularCrop
  ).into(this)
}

private fun createGlideRequest(
  context: Context,
  @DrawableRes src: Int,
  centerCrop: Boolean,
  circularCrop: Boolean
): RequestBuilder<Drawable> {
val req = Glide.with(context).load(src)
  if (centerCrop) req.centerCrop()
  if (circularCrop) req.circleCrop()
     return req
}

创建一个接受多个可选属性的 binding 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)
}

你可以这样使用它:

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

您还可以在 Owl - an official Android sample app on GitHub. See BindingAdapters.kt 的来源中找到示例。

@JvmStatic
@BindingAdapter("glide")
fun glide(view: ShapeableImageView, url: String?) {
   if (!url.isNullOrEmpty()) {
      Glide.with(view).load(url).into(view)
   }
}

布局:

<data>
     <import type="com.example.package.R"/>
</data>

<ImageView
     android:id="@+id/logo"
     android:contentDescription="@string/logo"
     android:scaleType="fitCenter"
     app:gif = "@{R.drawable.logo}" />

数据绑定实用程序:

@BindingAdapter("gif")
fun ImageView.setGif(res: Int) {
    Glide.with(this).load(res).into(this);
}