Android MVVM:如何将资源字符串从视图模型传递到视图?
我想在视图中显示文本。但是,文本不依赖于我可以直接显示的模型中的数据,而是依赖于状态枚举。取决于要在字符串资源文件中显示预定义文本的状态 例如,我在模型层中有以下枚举:Android MVVM:如何将资源字符串从视图模型传递到视图?,android,mvvm,android-resources,Android,Mvvm,Android Resources,我想在视图中显示文本。但是,文本不依赖于我可以直接显示的模型中的数据,而是依赖于状态枚举。取决于要在字符串资源文件中显示预定义文本的状态 例如,我在模型层中有以下枚举: enum class GreetingType { GREETING_FIRST_TIME, WELCOME_BACK, GOODBYE } 在my strings.xml中,我有相应的字符串: R.string.greeting_first_time R.string.welcome_back R.s
enum class GreetingType
{
GREETING_FIRST_TIME,
WELCOME_BACK,
GOODBYE
}
在my strings.xml中,我有相应的字符串:
R.string.greeting_first_time
R.string.welcome_back
R.string.goodbye
我的问题是:视图模型和视图之间的接口应该是什么样子?我是否应该通过:
枚举,例如GreetingType.再见
资源ID,例如R.string.bye
解析的字符串,例如context.resources.getStringR.string.bye
每种方法似乎都有缺点:
和1。二,。我需要视图中的映射逻辑。
和3。我需要视图模型中的上下文,这是我想要避免的。
有推荐的方法吗
我能否做到这两点:
通过避免if/else使视图保持哑状态
保持视图模型与Android框架保持清洁,即使用ViewModel而不是AndroidViewModel?
我发现的示例只处理直接显示的数据。取决于您的用例,但在viewModels中也有资源引用并不理想。因此,我建议您直接在视图活动或片段中分配它,例如:
fun setGreeting() { textView.setText(R.string.greeting_first_time) }
fun setWelcome() { textView.setText(R.string.welcome_back) }
fun setGoodbye() { textView.setText(R.string.goodbye) }
然后将它们显示在视图模型上,例如,如果是,则执行setGreeting如果是,则执行setWelcome,或使用枚举执行切换case,并在视图模型内调用相应的view.setGreeting。取决于您的用例,但在视图模型内也不理想使用资源引用。因此,我建议您直接在视图活动或片段中分配它,例如:
fun setGreeting() { textView.setText(R.string.greeting_first_time) }
fun setWelcome() { textView.setText(R.string.welcome_back) }
fun setGoodbye() { textView.setText(R.string.goodbye) }
然后将它们显示在视图模型上,例如,如果是这样,则执行setGreeting,如果是那样,则执行setWelcome,或对枚举执行切换,并在viewModel内调用相应的view.setGreeting。要在viewModel中使用上下文,可以使用需要applicationContext的AndroidViewModelapplication,然后使用Resources
示例如下:
val displayPropertyPrice=Transformations.mapselectedProperty{
application.applicationContext.getString
当它是以色列的时候{
true->R.string.display\u price\u monthly\u rental
false->R.string.display\u price
}这是我的价格
}
要在ViewModel中使用上下文,可以使用需要applicationContext的AndroidViewModelapplication,然后使用Resources
示例如下:
val displayPropertyPrice=Transformations.mapselectedProperty{
application.applicationContext.getString
当它是以色列的时候{
true->R.string.display\u price\u monthly\u rental
false->R.string.display\u price
}这是我的价格
}
对我来说,更好的选择是使用android 由于数据绑定,您的view.xml具有变量。因此,可以将viewModel直接传递到视图中 将简单的逻辑映射到视图中并不是一个缺点。在web开发中,这就是我们在模板中使用React或VueJs所做的。最重要的是保持简单 从这个角度来看,当您想要更改某些内容时,您知道您的显示逻辑每次都在您的视图中 如果显示逻辑将更加复杂,则可以创建一个 以下是一个例子:
class MyViewModel() : ViewModel() {
// prevent changing the value of the greeting var outside the viewModel
private val _greeting = MutableLiveData<GreetingType>()
// we can access greeting value from here
val greeting: LiveData<GreetingType>
get() = _greeting
fun setGreeting(g: GreetingType) {
if (_greeting.value != g) {
_greeting.value = g
}
}
}
您的数据绑定对象:
object MyFirstDatabinding {
@JvmStatic
@BindingAdapter("android:dispGreeting")
fun displayGreeting(txtView: TextView, greeting: GreetingType?) {
greeting?.let { g ->
val sentence = when(g) {
GREETING_FIRST_TIME -> view.context.getString(R.string.greeting_first_time)
WELCOME_BACK -> view.context.getString(R.string.welcome_back)
GOODBYE -> view.context.getString(R.string.goodbye)
}
txtView.setText(sentence)
}
}
}
你的观点
<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="your.package.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView"
android:dispGreeting="@{viewModel.greeting}" />
</ androidx.constraintlayout.widget.ConstraintLayout>
</layout>
对我来说,更好的选择是使用android 由于数据绑定,您的view.xml具有变量。因此,可以将viewModel直接传递到视图中 将简单的逻辑映射到视图中并不是一个缺点。在web开发中,这就是我们在模板中使用React或VueJs所做的。最重要的是保持简单 从这个角度来看,当您想要更改某些内容时,您知道您的显示逻辑每次都在您的视图中 如果显示逻辑将更加复杂,则可以创建一个 以下是一个例子:
class MyViewModel() : ViewModel() {
// prevent changing the value of the greeting var outside the viewModel
private val _greeting = MutableLiveData<GreetingType>()
// we can access greeting value from here
val greeting: LiveData<GreetingType>
get() = _greeting
fun setGreeting(g: GreetingType) {
if (_greeting.value != g) {
_greeting.value = g
}
}
}
您的数据绑定对象:
object MyFirstDatabinding {
@JvmStatic
@BindingAdapter("android:dispGreeting")
fun displayGreeting(txtView: TextView, greeting: GreetingType?) {
greeting?.let { g ->
val sentence = when(g) {
GREETING_FIRST_TIME -> view.context.getString(R.string.greeting_first_time)
WELCOME_BACK -> view.context.getString(R.string.welcome_back)
GOODBYE -> view.context.getString(R.string.goodbye)
}
txtView.setText(sentence)
}
}
}
你的观点
<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="your.package.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView"
android:dispGreeting="@{viewModel.greeting}" />
</ androidx.constraintlayout.widget.ConstraintLayout>
</layout>
最糟糕的事情是向viewModel添加上下文检出:最糟糕的事情是向viewModel添加上下文检出:谢谢。我还没有研究数据绑定,因为我想避免在XML文件中使用逻辑。我不知道绑定适配器。这似乎满足了我的要求。您有为绑定适配器编写单元测试的经验吗?这看起来可能是视图中包含逻辑的主要优势。我阅读了大量解决此问题的解决方案。你的想法让我完全满意!非常感谢。我还没有研究数据绑定,因为我想避免在XML文件中使用逻辑。我不知道绑定适配器。这似乎满足了我的要求。您有为绑定适配器编写单元测试的经验吗?这看起来可能是视图中包含逻辑的主要优势 解决这个问题的方法。你的想法让我完全满意!非常感谢你。