理想情况下,应该使用数据绑定,通过解析 xml 文件中的字符串可以轻松解决此问题。但是在现有项目中实现数据绑定可能太多了。
对于这样的情况,我创建了以下类。它涵盖了所有带或不带参数的字符串情况,并且不需要 viewModel 扩展 AndroidViewModel 并且这种方式也涵盖了 Locale 更改的事件。
class ViewModelString private constructor(private val string: String?,
@StringRes private val stringResId: Int = 0,
private val args: ArrayList<Any>?){
//simple string constructor
constructor(string: String): this(string, 0, null)
//convenience constructor for most common cases with one string or int var arg
constructor(@StringRes stringResId: Int, stringVar: String): this(null, stringResId, arrayListOf(stringVar))
constructor(@StringRes stringResId: Int, intVar: Int): this(null, stringResId, arrayListOf(intVar))
//constructor for multiple var args
constructor(@StringRes stringResId: Int, args: ArrayList<Any>): this(null, stringResId, args)
fun resolve(context: Context): String {
return when {
string != null -> string
args != null -> return context.getString(stringResId, *args.toArray())
else -> context.getString(stringResId)
}
}
}
用法
例如,我们有这个带有两个参数的资源字符串
<string name="resource_with_args">value 1: %d and value 2: %s </string>
在 ViewModel 类中:
myViewModelString.value = ViewModelString(R.string.resource_with_args, arrayListOf(val1, val2))
在 Fragment 类中(或任何有可用上下文的地方)
textView.text = viewModel.myViewModelString.value?.resolve(context)
请记住,*args.toArray() 上的 * 不是输入错误,因此请不要删除它。它的语法将数组表示为Object...objects,Android 内部使用它而不是Objects[] objects,这会导致崩溃。