如何使用Glide实现数据绑定的图片加载?

20

我正在尝试使用数据绑定加载图片,但一直没有成功。我的问题出在哪里?以下是我的代码和布局构造。

MyItemViewModel.kt

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

布局文件.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"/>

2
你需要将你的 fun loadImage 设为静态方法,并且加上 @JvmStatic 标记。如果出现错误,可以将其移动到 companion object 中。 - Jeel Vankhede
1
@Hasan,具体错误是URL为“null”,还是出现了一些编译时错误? - yash786
1
您的清单中是否具有互联网权限? - Blackbelt
1
@Blackbelt 是的,已添加。 - Hasan Kucuk
1
请查看我在答案中提到的链接,它肯定会对你有所帮助。 - GOVIND DIXIT
显示剩余5条评论
8个回答

13

您需要将url参数设置为可空,并像这样防止null:

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

8

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

但是这将生成'编译时错误',即"方法不能在类内部是静态的",因此它应该移动到伴生对象命名对象中。

在您的情况下,您在类成员级别上拥有方法,因此将其移动到伴生对象中将有所帮助。因此,对于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
}

注意:还要删除带有=的方法声明。绑定方法应该有返回类型Unit

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

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

  1. 在从Activity/Fragment中使用它之前,您的视图应该已经被附加。这种方法的最佳用例是自定义视图/ViewGroup。

  2. 在使用此方法之前,请考虑布局层次结构,因为不建议在嵌套/大型层次结构布局中使用该方法。对于这样的布局,它变得效率低下。

  3. 还要注意,如果视图位于非支持片段类中或上下文是非支持片段,则可能会产生嘈杂的日志,如documentation所示,首先迁移到支持库(现在被认为是AndroidX)然后再使用此方法!


在 Glide 的文档中,哪里规定了 BindingAdapter 方法必须是静态的? - IgorGanapolsky
我认为使用Glide.with(view)更好,如果您检查代码和文档,这将尊重片段(或活动)的生命周期,该视图显示在其中。 with(context)“仅适用于应用程序级别选项,并且不会根据生命周期事件启动或停止...适用于将在正常片段或活动生命周期之外使用的资源”。 - hmac

4

创建一个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}" />

你还可以在GitHub上的官方Android示例应用程序Owl的源代码中找到一个示例。请参阅BindingAdapters.kt。源代码链接:OwlBindingAdapters.kt

4

这对我来说很好用。

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


    }

绑定需要添加哪个命名空间? - Sathish Gadde
1
@SathishGadde,请编写应用程序而不是绑定。 - Amr

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

0

我认为最佳实践应该是在layout.xml中创建一个类型为string的imageUrl变量。BindingAdapter应该在model类中。此外,BindingAdapter方法应该是静态的,正如评论中指出的那样。您可以通过使用带有@JvmStatic注释的伴生对象进行包装来实现。有关更多详细信息,请查看this

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

1
在运行时获取图像URL,我们必须提到存储URL对象的类的路径。 - yash786
1
绑定适配器应该在哪个类中呢?是 Model.kt、AlbumItemViewModel.kt、AlbumViewModel.kt 还是 AlbumAdapter.kt 呢? - Hasan Kucuk
1
BindingAdapter 应该在模型类中。 - GOVIND DIXIT
在 RowAlbumListBindingImpl 类中,所需的 DataBindingComponent 为空。com.myapp.app.model.AlbumList.Companion 中的 BindingAdapter 不是静态的,并且需要从 DataBindingComponent 检索对象才能使用。如果您不使用接受 DataBindingComponent 的膨胀方法,请使用 DataBindingUtil.setDefaultComponent 或使所有 BindingAdapter 方法都为静态方法。 - Hasan Kucuk
是的,正如已经提到的那样,bindingAdapter方法应该是静态的。 - GOVIND DIXIT

0

使用 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
}

0

布局:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接