在 Android 数据绑定中使用来自视图模型的可空字符串资源 ID
Using a nullable string resource id from view model in Android data binding
我正在尝试将 API 错误(异常)映射到我的视图模型中的字符串资源。我的视图模型如下所示。
@HiltViewModel
class AccountViewModel @Inject constructor(accountRepository: AccountRepository) : ViewModel() {
val isLoadingProfile = MutableLiveData(false)
val profile = MutableLiveData<Profile>()
val profileLoadError = MutableLiveData<Int>()
fun loadProfile() {
isLoadingProfile.postValue(true)
viewModelScope.launch(Dispatchers.IO) {
try {
profile.postValue(accountRepository.getProfile())
} catch (e: Throwable) {
// assign String resource id to profileLoadError
profileLoadError.postValue(
when (e) {
is NetworkError -> R.string.network_error
else -> R.string.unknown_error
}
)
} finally {
isLoadingProfile.postValue(false)
}
}
}
}
我的错误文本视图 XML 如下所示。
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.profileLoadError ?? ``}"
android:visibility="@{viewModel.profileLoadError != null ? View.VISIBLE : View.GONE}" />
但是当我尝试 运行 时遇到 class 转换异常。
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.CharSequence
如果我像下面这样从数据绑定表达式中删除 null
合并运算符,我会得到一个找不到资源的异常。
android:text="@{viewModel.profileLoadError}"
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x0
我知道这是个愚蠢的问题,但我该如何解决这个问题?
是 NetworkError -> R.string.network_error -> 在这一行中,您将字符串返回到 post 类型 Int.That 的 profileLoadError 的值,这就是您获得 ClassCastException 的原因。
所以把LiveData的类型改成String
val profileLoadError = MutableLiveData()
根据@androidLearner 的建议,我为 android:text
属性创建了一个绑定适配器。
@BindingAdapter("android:text")
fun TextView.setText(@StringRes resId: Int?) {
resId ?: return
if (resId == ResourcesCompat.ID_NULL) {
text = ""
} else {
setText(resId)
}
}
现在,我可以传递字符串 ID 而不必担心其是否为空。
android:text="@{viewModel.profileLoadError}"
我正在尝试将 API 错误(异常)映射到我的视图模型中的字符串资源。我的视图模型如下所示。
@HiltViewModel
class AccountViewModel @Inject constructor(accountRepository: AccountRepository) : ViewModel() {
val isLoadingProfile = MutableLiveData(false)
val profile = MutableLiveData<Profile>()
val profileLoadError = MutableLiveData<Int>()
fun loadProfile() {
isLoadingProfile.postValue(true)
viewModelScope.launch(Dispatchers.IO) {
try {
profile.postValue(accountRepository.getProfile())
} catch (e: Throwable) {
// assign String resource id to profileLoadError
profileLoadError.postValue(
when (e) {
is NetworkError -> R.string.network_error
else -> R.string.unknown_error
}
)
} finally {
isLoadingProfile.postValue(false)
}
}
}
}
我的错误文本视图 XML 如下所示。
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.profileLoadError ?? ``}"
android:visibility="@{viewModel.profileLoadError != null ? View.VISIBLE : View.GONE}" />
但是当我尝试 运行 时遇到 class 转换异常。
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.CharSequence
如果我像下面这样从数据绑定表达式中删除 null
合并运算符,我会得到一个找不到资源的异常。
android:text="@{viewModel.profileLoadError}"
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x0
我知道这是个愚蠢的问题,但我该如何解决这个问题?
是 NetworkError -> R.string.network_error -> 在这一行中,您将字符串返回到 post 类型 Int.That 的 profileLoadError 的值,这就是您获得 ClassCastException 的原因。
所以把LiveData的类型改成String
val profileLoadError = MutableLiveData()
根据@androidLearner 的建议,我为 android:text
属性创建了一个绑定适配器。
@BindingAdapter("android:text")
fun TextView.setText(@StringRes resId: Int?) {
resId ?: return
if (resId == ResourcesCompat.ID_NULL) {
text = ""
} else {
setText(resId)
}
}
现在,我可以传递字符串 ID 而不必担心其是否为空。
android:text="@{viewModel.profileLoadError}"