首页 > 解决方案 > NotFoundException: 绑定字符串资源时字符串资源 ID #0x0

问题描述

我目前正在使用绑定来使用 android 视图模型动态设置各种文本视图的文本。目前,视图模型看起来像这样:

class MyViewModel(
  resources: Resources,
  remoteClientModel: Model = Model()
) : ObservableViewModel() {

  init {
    observe(remoteClientModel.liveData) {
      notifyChange()
    }

  fun getTextViewTitle(): String = when {
    someComplicatedExpression -> resources.getString(R.string.some_string, null)
    else -> resources.getString(R.string.some_other_string)
  }
}

和 xml 布局:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
  <import type="android.view.View"/>

  <variable
    name="viewModel"
    type="my.app.signature.MyViewModel"/>
  </data>

  <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
      android:id="@+id/title"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@{viewModel.textViewTitle}"
      android:textAlignment="center"
      android:textStyle="bold"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="parent"/>

  </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

但是我想删除注入视图模型的“资源:资源”,因为资源与活动耦合。代码现在只返回字符串资源 id:

  fun getTextViewTitle(): Int = when {
    someComplicatedExpression -> R.string.some_string
    else -> R.string.some_other_string
  }

因此,我删除了活动依赖项。编译器认为这很好,但它在运行时崩溃并出现以下异常:android.content.res.Resources$NotFoundException: String resource ID #0x0。

尝试使用以下方法将 lifeCycleOwner 附加到绑定时会发生这种情况:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    // Some more code....
    binding.lifecycleOwner = activity
    // Some more code....

我不确定如何从视图模型中删除资源依赖项,而不会在运行时崩溃。

编辑:

澄清一下:我的示例中的 ObservableViewModel 与此处找到的完全相同:

https://developer.android.com/topic/libraries/data-binding/architecture

用于执行 notifyChange。

标签: androidandroid-lifecycle

解决方案


这里的问题是代码试图调用textView.setText(0)导致错误,因为没有 id 为 0x0 的字符串资源。发生这种情况是因为getTextViewTitle()return anInt并且视图绑定功能将使其默认为 0(初始化时)。

https://developer.android.com/topic/libraries/data-binding/expressions#property_reference

从文档

避免空指针异常

生成的数据绑定代码会自动检查空值并避免空指针异常。例如,在表达式 @{user.name} 中,如果 user 为 null,则 user.name 被赋予其默认值 null。如果引用 user.age,其中 age 的类型为 int,则数据绑定使用默认值 0。

也许这样的事情可以工作,

android:text='@{viewModel.textViewTitle == 0 ? "" : @string{viewModel.textViewTitle}}'

或者

android:text='@{viewModel.textViewTitle, default=""}'

推荐阅读