关于数据绑定、实时数据和可绘制对象的问题

Question on data binding, live data and drawable

我正在尝试将可绘制对象与实时数据进行数据绑定,但 运行 遇到此错误

java.lang.RuntimeException: Failed to call observer method
Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x0

我的xml片段(只粘贴了相关部分)

<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>
        <import type="androidx.core.content.ContextCompat" />
        <variable name="location" type="String"/>
        <variable name="viewModel"
            type="com.marty.dang.polarpointsweatherapp.presentation.viewmodel.DailyWeatherViewModel"/>
    </data>
        <ImageView
            android:id="@+id/homeFrag_weather_icon"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_marginTop="40dp"

            android:src="@{ContextCompat.getDrawable(context, viewModel.iconObservable)}"

            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.497"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/homeFrag_title_text_view" />

我的视图模型(只粘贴了相关部分)

val iconObservable: MutableLiveData<Int> by lazy { MutableLiveData<Int>() }

    private fun determineWeatherIcon(weatherDescription: String)  {
        val icon = when(weatherDescription){
            "Thunderstorm" -> R.drawable.thunderstorm_icon
            "Drizzle" -> R.drawable.rain_icon
            "Rain" -> R.drawable.rain_icon
            "Snow" -> R.drawable.snow_icon
            "Clear" -> R.drawable.sun_icon
            "Clouds" -> R.drawable.cloudy_icon
            else -> R.drawable.cloudy_icon
        }

        iconObservable.postValue(icon)
    }

我的可绘制文件夹

但是,如果我只使用常规变量而不是可变的实时数据变量,它工作正常。

var weatherIcon = R.drawable.snow_icon

private fun determineWeatherIcon(weatherDescription: String)  {
    weatherIcon = when(weatherDescription){
        "Thunderstorm" -> R.drawable.thunderstorm_icon
        "Drizzle" -> R.drawable.rain_icon
        "Rain" -> R.drawable.rain_icon
        "Snow" -> R.drawable.snow_icon
        "Clear" -> R.drawable.sun_icon
        "Clouds" -> R.drawable.cloudy_icon
        else -> R.drawable.cloudy_icon
    }
}

android:src="@{ContextCompat.getDrawable(context, viewModel.weatherIcon)}"

如有任何帮助,我们将不胜感激。谢谢!

iconObservable.value 在你的 xml 上试试这个,它会起作用

您可以在 xml 中使用 app:imageResource 属性:

<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="location" type="String"/>
        <variable name="viewModel" type="com.marty.dang.polarpointsweatherapp.presentation.viewmodel.DailyWeatherViewModel"/>
    </data>
    
    <ImageView
        android:id="@+id/homeFrag_weather_icon"
        app:imageResource="@{viewModel.iconObservable}"
        ... />
...

在您的 viewModel 中,您应该具有以下 属性:

val iconObservable: MutableLiveData<Int>

你可以有以下方法:

private fun determineWeatherIcon(weatherDescription: String)  {
    iconObservable.value = when(weatherDescription){
        "Thunderstorm" -> R.drawable.thunderstorm_icon
        "Drizzle" -> R.drawable.rain_icon
        "Rain" -> R.drawable.rain_icon
        "Snow" -> R.drawable.snow_icon
        "Clear" -> R.drawable.sun_icon
        "Clouds" -> R.drawable.cloudy_icon
        else -> R.drawable.cloudy_icon
    }
}

您不需要 postValue,除非您在后台线程中设置该值。

在您的片段 class 中,您应该将 viewModellifecycleOwner 设置为您的 binding:

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = YourFragmentBinding.inflate(inflater, container, false)
    binding.viewModel = viewModel
    binding.lifecycleOwner = viewLifecycleOwner
    return binding.root
}