【问题标题】:NotFoundException: String resource ID #0x0 when binding string resourceNotFoundException: 绑定字符串资源时字符串资源 ID #0x0
【发布时间】:2021-10-02 08:21:15
【问题描述】:

我目前正在使用绑定来动态设置使用 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。

【问题讨论】:

  • 我认为您的应用程序因此而崩溃 constructor of your ViewModel 从构造函数中删除依赖项。如果您想使用ViewModel 中的资源,请使用AndroidViewModel
  • AndroidViewModel 有一个与注入不兼容的条件:“应用程序上下文感知 ViewModel。子类必须有一个接受 Application 作为唯一参数的构造函数。”就我而言,我无法使用 AndroidViewModel,因为我想注入执行 IO 任务的模型。
  • 错误是因为它试图将0(整数)设置为textview资源id。您应该重新检查并确保 getTextViewTitle() 不返回 0。

标签: android android-lifecycle


【解决方案1】:

这里的问题是代码试图调用textView.setText(0),这会导致错误,因为没有 id 为 0x0 的字符串资源。发生这种情况是因为 getTextViewTitle() 返回一个 Int 并且视图绑定功能会将其默认为 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=""}'

【讨论】:

  • 这行得通,但我不想在视图中引入逻辑。我会发布一个更适合我的情况的替代答案。
【解决方案2】:

要解决这个问题,只需在视图中创建一个可用的上下文,以便您可以在视图中调用 context.getString(...)。

 <data>
    <import type="androidx.core.content.ContextCompat" />

    <variable
      name="viewModel"
      type="my.application.path.SomeViewModel" />
 </data>

  <....
      ....
      android:text="@{context.getString(viewModel.textResource)}"
      ...
  />

【讨论】:

  • 很久没处理这个问题了,不过你也可以使用bindingAdapters来解决这个问题:code@BindingAdapter("textResource") fun TextView.setTextResource(resId: Int?) { resId ?: return text = context.getString(resId) } code 也许这对你有用。
【解决方案3】:

只需将您的 int 值转换为 String 即可避免这种迷恋

android:text='@{String.valueOf(viewModel.profile.walletBalance)}'

【讨论】:

    【解决方案4】:

    在某些情况下,您的绑定变量本身可以为空

    <data>
        <variable
            name="viewModel"
            type="SomeViewModel" 
        />
    </data>
    
    <TextView
        android:text="@{viewModel == null ? "" : viewModel.textViewTitle}"
    />
    

    【讨论】:

      猜你喜欢
      • 2019-08-16
      • 1970-01-01
      • 2023-01-21
      • 1970-01-01
      • 2023-03-25
      • 2013-06-27
      • 2021-05-09
      • 2012-06-26
      相关资源
      最近更新 更多