【问题标题】:Android - databinding/livedata/resourceId TextView errorAndroid - 数据绑定/livedata/resourceId TextView 错误
【发布时间】:2020-07-22 02:24:20
【问题描述】:

我正在使用数据绑定,我想通过 LiveData 将文本设置为 TextView,如下所示:

binding.lifecycleOwner = viewLifecycleOwner
binding.viewModel = viewModel

设置文本视图

viewModel.toolbarTitle.postValue(R.string.profile_title_my_documents)

查看模型实现

val toolbarTitle = MutableLiveData<@androidx.annotation.StringRes Int>()

然后是 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="viewModel"
        type="packagename.MyViewModel"
        />
  </data>

  <TextView
        android:id="@+id/title"
        style="@style/toolbar_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{viewModel.toolbarTitle}"
        />
</layout>

所以基本上如果我删除 LiveData 并使用 Int 值它工作正常,但使用 LiveData 我得到一个例外:

2020-04-09 14:38:59.929 19744-19744/ E/AndroidRuntime: FATAL EXCEPTION: main
    Process: , PID: 19744
    java.lang.RuntimeException: Failed to call observer method
        at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:226)

...
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x0
        at android.content.res.Resources.getText(Resources.java:348)
        at android.widget.TextView.setText(TextView.java:5831)
        at ToolbarBindingImpl.executeBindings(ToolbarBindingImpl.java:146)
        at androidx.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:472)
        at androidx.databinding.ViewDataBinding.executeBindingsOn(ViewDataBinding.java:486)
        at MyBindingImpl.executeBindings(MyBindingImpl.java:151)
        at androidx.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:472)
        at androidx.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:444)
        at androidx.databinding.ViewDataBinding$OnStartListener.onStart(ViewDataBinding.java:1685)
        at java.lang.reflect.Method.invoke(Native Method)

它最有可能崩溃,因为当屏幕打开时,livedata int 值为 O,它被发送到 textview 并崩溃,因为没有 resId == 0

如何解决这个问题?第二个问题,这是使用这样的 livedata 的好方法还是没有必要?

更新 我用它来绕过零值:

android:text='@{viewModel.toolbarTitle == 0 ? "" : context.getString(viewModel.toolbarTitle)}'

【问题讨论】:

    标签: android data-binding android-livedata


    【解决方案1】:

    是的,这是正确的方法,但您可以尝试以下一些修改。

    在你的ViewModel

    val toolbarTitle = MutableLiveData<String>()
    

    将其更改为字符串。

    同时为它设置一个值

    viewModel.toolbarTitle.postValue(context.getString(R.string.profile_title_my_documents))
    

    您可以拥有应用程序上下文,这将起作用。

    【讨论】:

    • 谢谢这绝对有效,但老实说,每次都必须添加 getstring 需要额外的努力,我认为有一些方法可以自动使用 resIds,但这是有道理的,因为它如果值为零,通常会崩溃
    • 好吧,我想我明白了,我把它改为:android:text='@{viewModel.toolbarTitle == 0 ? "" : context.getString(viewModel.toolbarTitle)}'
    • 是的,尽管您可以尝试为实时数据设置默认值。 val toolbarTitle = MutableLiveData&lt;@androidx.annotation.StringRes Int&gt;().apply { postValue(R.string.profile_title_my_documents) }
    • 您在 ViewModel 中传递了 Context,这有点违背了 ViewModel 的目的。阅读stackoverflow.com/a/51451877/311420
    【解决方案2】:

    你也可以直接从activity或fragment设置为xml。在这里,您从活动中所做的事情是在 viewmodel 中设置该值,之后您将 viewmodel 从活动设置为 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="viewModel"
                type="packagename.MyViewModel"
                />
    
            <variable
                name="title"
                type="String" />
        </data>
    
        <TextView
            android:id="@+id/title"
            style="@style/toolbar_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{title}"
            />
    </layout>
    

    来自活动:

    bindObject.title= "Title"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-08
      • 1970-01-01
      • 2019-12-14
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多