#android #kotlin #android-databinding #android-architecture-components #android-livedata
#Android #kotlin #android-привязка данных #android-архитектура-компоненты #android-livedata
Вопрос:
Я пытаюсь использовать привязку данных для добавления изображения в ImageView.
Я извлекаю объект из базы данных Room и предоставляю URL-адрес заголовка и изображения как LiveData. Я могу установить заголовок, но настройка изображения не выполняется.
Вот журнал ошибок
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter imageUrl
at com.sample.databinding.detail.ArticleDetailsViewModel$Companion.loadImage(Unknown Source:7)
at com.sample.databinding.detail.ArticleDetailsViewModel.loadImage(Unknown Source:2)
at com.sample.databinding.detail.databinding.ActivityArticleDetailsBindingImpl.executeBindings(ActivityArticleDetailsBindingImpl.java:198)
at androidx.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:448)
at androidx.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:420)
at androidx.databinding.ViewDataBinding$OnStartListener.onStart(ViewDataBinding.java:1633)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:215)
Вот строка в сгенерированном файле, которая не выполняется
if ((dirtyFlags amp; 0x19L) != 0) {
// api target 1
com.sample.databinding.detail.ArticleDetailsViewModel.loadImage(this.backdrop, articleDetailsViewModelImageUrlGetValue);
}
Вот мой код
activity_details.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="articleDetailsViewModel"
type="com.monzo.androidtest.detail.ArticleDetailsViewModel" />
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@ id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@ id/appbar"
android:layout_width="match_parent"
android:layout_height="256dp"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@ id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@ id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
app:imageSource="@{articleDetailsViewModel.imageUrl}"/>
<androidx.appcompat.widget.Toolbar
android:id="@ id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="@{articleDetailsViewModel.articleTitle}"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
ActivityDetailsViewModel.kt
package com.sample.databinding.detail
import android.app.Application
import android.widget.ImageView
import androidx.core.text.HtmlCompat
import androidx.databinding.BindingAdapter
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel
import com.bumptech.glide.Glide
import com.sample.databinding.articles.model.Article
import com.sample.databinding.data.ArticlesDao
import kotlinx.coroutines.*
class ArticleDetailsViewModel(
val database: ArticlesDao,
val application: Application,
val articleID: String) : ViewModel() {
val article = database.getSpecificPost(articleID)
val imageUrl = Transformations.map(article) {article.value?.thumbnail}
val articleTitle = Transformations.map(article) {article.value?.title}
companion object {
@JvmStatic
@BindingAdapter("bind:imageSource")
fun loadImage(view: ImageView, imageUrl: String) {
if (!imageUrl.isEmpty()) {
Glide.with(view.getContext())
.load(imageUrl)
.into(view)
}
}
}
}
Комментарии:
1. Что делают ваши кнопки запуска фрагмента кода ?
Ответ №1:
Видите, вы написали хороший код, но есть проблема в адаптере привязки
@JvmStatic
@BindingAdapter("bind:imageSource")
fun loadImage(view: ImageView, imageUrl: String) {
if (!imageUrl.isEmpty()) {
Glide.with(view.getContext())
.load(imageUrl)
.into(view)
}
}
В этом коде вы ожидаете not null ImageUrl, но во время выполнения это значение равно null. Итак, это создает исключение.
Чтобы решить эту проблему, вы должны указать параметр ImageUrl nullable . И затем вы должны проверить, является ли ImageUrl нулевым или пустым. Итак, ваш метод привязки адаптера будет таким :
@JvmStatic
@BindingAdapter("bind:imageSource")
fun loadImage(view: ImageView, imageUrl: String?) {
if (!imageUrl.isNullOrBlank()) {
Glide.with(view.getContext())
.load(imageUrl)
.into(view)
}
}
Надеюсь, это поможет. Счастливого кодирования 🙂
Комментарии:
1. Как мы узнаем, что вызывает
imageUrl
значение null?
Ответ №2:
Это должно быть
imageUrl?.let {
Glide.with(view.getContext())
.load(imageUrl)
.into(view)
}
Комментарии:
1. в вашем коде сбой был исправлен, но изображение не отображается
2. Потому
imageUrl
что равно нулю. Что вы ожидаете от «отображения» для null?3. Я не ожидаю, что что-либо будет отображаться для null …. но если вы посмотрите «ВНИМАТЕЛЬНО» … ImageUrl — это LiveData…. Итак, я ожидал, что код Glide будет выполняться снова один раз, он имеет значение…. точно так же, как это делается для articleTitle
4. Каково ваше решение, @PrateekPhoenix?