【问题标题】:How to databinding image loading with Glide?如何使用 Glide 进行数据绑定图像加载?
【发布时间】:2019-11-15 07:26:36
【问题描述】:

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

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"/>

【问题讨论】:

  • 您需要将 fun loadImage 设为静态。把@JvmStatic 给它。如果它提供错误,则将其移动到伴随对象。
  • @Hasan 确切的错误是 url 是“null”还是发生了一些编译时错误。?
  • @JeelVankhede 它给出了错误。我再次转移到模型中给出了错误。 (只有命名对象和伴生对象中的成员可以用@JvmStatic注解)
  • 你的函数应该是 void remove = and but {} @HasanKucuk
  • @yash786 url 已满,但我无法加载带有数据绑定的 imageview。

标签: android kotlin android-databinding


【解决方案1】:

我认为最好的做法应该是在 layout.xml 中为 string 类型的 imageUrl 创建一个单独的变量。 BindingAdapter 应该在模型类中。此外,如 cmets 中所指出的,BindingAdapter 方法应该是静态的。您可以通过使用 @JvmStatic 注释包装在伴随对象中来做到这一点。更多详情请查看this

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

【讨论】:

  • 要在运行时获取imageurl,我们必须提到存储url对象的类的路径
  • bindinAdapter 应该在哪个类中? Model.kt、AlbumItemViewModel.kt、AlbumViewModel.kt、AlbumAdapter.kt?
  • BindingAdapter 应该在模型类中
  • :RowAlbumListBindingImpl 类中所需的 DataBindingComponent 为空。 com.myapp.app.model.AlbumList.Companion 中的 BindingAdapter 不是静态的,需要使用从 DataBindingComponent 检索的对象。如果您不使用采用 DataBindingComponent 的膨胀方法,请使用 DataBindingUtil.setDefaultComponent 或将所有 BindingAdapter 方法设为静态。
  • 是的,如前所述,bindingAdapter 方法应该是静态的。
【解决方案2】:

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

但这会产生'编译时错误',即“类内的方法不能是静态的”,因此应该将其移至companion object 或命名对象

在您的情况下,您在 类成员级别 拥有方法,因此将其移至 companion object 会有所帮助。所以对于 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 使用视图之前,应附加您的视图。此方法的最佳用例是自定义视图/视图组。

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

  3. 1234563作为 AndroidX) 而不是在使用此方法之前!

【讨论】:

  • Glide 中规定 BindingAdapter 方法应该是静态的文档在哪里?
  • 我认为使用Glide.with(view) 更可取,如果您检查代码和文档,这将尊重显示视图的片段(或活动)的生命周期。with(context)“只会有应用程序级别选项应用,不会根据生命周期事件启动或停止...适用于将在正常片段或活动生命周期之外使用的资源"
【解决方案3】:

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

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

【讨论】:

    【解决方案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)
            }
    
    
        }
    

    【讨论】:

    • 绑定需要添加哪个命名空间:
    • @SathishGadde,编写应用程序而不是绑定
    【解决方案5】:

    像这样使用 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
    }
    

    【讨论】:

      【解决方案6】:

      创建一个接受多个可选属性的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 的源代码中找到示例 - GitHub 上的官方 Android 示例应用程序。见BindingAdapters.kt

      【讨论】:

        【解决方案7】:
        @JvmStatic
        @BindingAdapter("glide")
        fun glide(view: ShapeableImageView, url: String?) {
           if (!url.isNullOrEmpty()) {
              Glide.with(view).load(url).into(view)
           }
        }
        

        【讨论】:

          【解决方案8】:

          布局:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-05-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多