0
votes

context: data binding with a ViewModel, which gets data from a remote source in the form of JSON. I want to display a textual value from that JSON in a TextView, but if the data is absent in the JSON, I want to fall back to a string defined in strings.xml.

android:text="@{viewModel.theText}"

How I currently solved it is with a custom binding adapter that accepts an Any, and checks if the value is an Int or String: app:anyText="@{viewModel.theText}". The viewModel has something like val theText = json.nullableString ?: R.string.placeholder.

I'm guessing that this is a problem more people deal with, and I was hoping if someone knows a more elegant solution.

2

2 Answers

1
votes

You could provide Application context to your ViewModel or Resources and then do something like this:

val theText = json.nullableString ?: resources.getString(R.string.placeholder)

The other option would be keep using binding adapter like you do but I would wrap text input in another object like this:

data class TextWrapper(
   val text: String?,
   @StringRes val default: Int
)

@BindingAdapter("anyText")
   fun TextView.setAnyText(textWrapper: TextWrapper) {
   text = textWrapper.text ?: context.getString(textWrapper.default)
}

val theText = TextWrapper(text = json.nullableString, default = R.string.placeholder)
1
votes

You do not need an adapter to handle this use Null coalescing operator operator ?? in xml.

Try below code:

android:text="@{viewModel.theText?? @string/your_default_text}"

Use case :

The null coalescing operator (??) chooses the left operand if it isn't null or the right if the former is null.

P.S: lean more about DB and expressions here-> https://developer.android.com/topic/libraries/data-binding/expressions