如何使用 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)
:
在使用 Activity/Fragment 之前,应附加您的视图。此方法的最佳用例是 Custom View/ViewGroup.
在使用此方法之前考虑布局层次结构,因为不鼓励太多 nested/large 层次结构布局使用该方法。这样的布局会变得低效。
另请注意,如果视图位于 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);
}
我正在尝试使用数据绑定加载图像。但我从来没有克服它。我的问题在哪里?下面是我的代码和布局构造。
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 typeUnit
.
编辑: 也可以按照@hmac 在评论中的建议使用方法 Glide.with(view)
,但是 ...
使用此之前需要考虑的事项 Glide.with(view)
:
在使用 Activity/Fragment 之前,应附加您的视图。此方法的最佳用例是 Custom View/ViewGroup.
在使用此方法之前考虑布局层次结构,因为不鼓励太多 nested/large 层次结构布局使用该方法。这样的布局会变得低效。
另请注意,如果视图位于 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);
}