Search code examples
androiddata-bindingkotlin

ResourcesNotFoundException when binding Int to a TextView


Binding an Int value to a TextView causes a Resources$NotFoundException with message "String resource ID #0x2a" (where 0x2a is the value of the Int). Why does this happen, and how can it be fixed?

Sample code: * layout/activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools">

        <data>
            <variable name="data" type="com.example.Thing" />
        </data>

        <LinearLayout tools:context=".MainActivity">
            <TextView android:text="@{data.x}"/>
        </LinearLayout>
    </layout>
  • Thing.kt:

    package com.example
    
    data class Thing(
        var x:Int = 42
    )
    
  • MainActivity.kt:

    package com.example
    
    import android.databinding.DataBindingUtil
    import android.os.Bundle
    import android.support.v7.app.AppCompatActivity
    import com.example.databinding.ActivityMainBinding
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            var activityMain:ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
            activityMain.data = Thing()
        }
    }
    

Solution

  • TextView.setText(int), which was created before data binding was added to Android, interprets its argument as a resource identifier. To bind an integer to a TextView, convert the value with Integer.toString(int) or String.valueOf(int) (Int.toString apparently isn't available, as the value is unboxed):

        <TextView android:text="@{Integer.toString(data.x)}"/>
    

    If TextView.setText(int) didn't exist, you could also write a binding adapter to automatically convert between the bound value type and the type the View displays.