Android:以正确的方式应用 MVVM(第三部分)
Android: Applying MVVM the correct way (Part III)
为了使我的 mvvm 迁移达到最佳效果,我从社区获得了宝贵的帮助,但仍然对一些问题有疑问,例如:
我已将下一个方法从 activity 移至 ViewModel(因为它主要是业务),但不确定它是否完全正确,因为它处理视图。其中一个参数是一个以编程方式创建的 ImageView,我会说即使它是以编程方式创建的,它仍然是一个视图,并且当 VM 不被支持时,我间接将上下文传递给 VM(并直接传递一个视图元素)处理视图。
简而言之,我不确定 - 是 mvvm strict - 是否可以接受将此方法(或处理以编程方式创建的视图的任何方法)移动到 VM。
public void setCheckBoxCheckedState_TestMode(List<AnswerDTO> answers,
int pageNumber, int cbSelectedId, ImageView cbAnswer)
{
for (int j = 0; j < answers.size(); j++) {
int cbIndex = answers.size() * pageNumber + j;
if (cbIndex != cbSelectedId) {
setCheckBoxUnchecked_TestMode(cbIndex);
String strRest = cbAnswer.getTag().toString().substring(1);
cbAnswer.setTag("0" + strRest);
} else {
String cbAnswerJTag = cbAnswer.getTag().toString();
String cbAnswerJState = cbAnswerJTag.split("@")[0];
if (cbAnswerJState.equals("1")) { // 0=>unchecked|1=>checked
setCheckBoxUnchecked_TestMode(cbIndex);
cbAnswer.setTag("0@" + cbAnswerJTag.split("@")[1]);
} else {
setCheckBoxChecked_TestMode(cbIndex);
cbAnswer.setTag("1@" + cbAnswerJTag.split("@")[1]);
}
}
}
}
首先,任何时候您以编程方式创建 Views
,您都可能走错了路。您可能希望 RecyclerView
为您执行此操作。另一个巨大的危险信号是您正在使用 getTag()
在 ImageView
中存储信息。无论这些信息是什么,它都应该存储在列表或其他一些数据结构中(可能只是在您已经拥有的 List<AnswerDTO>
中)。
基本上,当您应该首先学习更多核心 Android 概念时,您正在尝试实施 MVVM。以 class 开头,例如 this one.
实际上,您应该告诉视图模型什么事件发生了变化(例如 viewModel.onSelectionChange(itemDataId)
),然后视图模型应该知道它需要更改哪些“数据”以更新视图模型的内部状态, 这应该被视图观察到,通常与数据绑定。
目前您正在为视图模型提供“视图”相关对象 - ImageView
- 它不应直接在视图对象上设置状态,即基于视图模型状态的视图关注点。看起来您只是将视图函数移动到视图模型,但它不属于那里。
像这样:
视图 <-- 数据绑定 --> 视图模型 <------> 模型
或没有数据绑定:
视图 -- 事件 ---> ViewModel <------> 模型
视图<----数据更新---视图模型<------>模型
为了使我的 mvvm 迁移达到最佳效果,我从社区获得了宝贵的帮助,但仍然对一些问题有疑问,例如:
我已将下一个方法从 activity 移至 ViewModel(因为它主要是业务),但不确定它是否完全正确,因为它处理视图。其中一个参数是一个以编程方式创建的 ImageView,我会说即使它是以编程方式创建的,它仍然是一个视图,并且当 VM 不被支持时,我间接将上下文传递给 VM(并直接传递一个视图元素)处理视图。
简而言之,我不确定 - 是 mvvm strict - 是否可以接受将此方法(或处理以编程方式创建的视图的任何方法)移动到 VM。
public void setCheckBoxCheckedState_TestMode(List<AnswerDTO> answers,
int pageNumber, int cbSelectedId, ImageView cbAnswer)
{
for (int j = 0; j < answers.size(); j++) {
int cbIndex = answers.size() * pageNumber + j;
if (cbIndex != cbSelectedId) {
setCheckBoxUnchecked_TestMode(cbIndex);
String strRest = cbAnswer.getTag().toString().substring(1);
cbAnswer.setTag("0" + strRest);
} else {
String cbAnswerJTag = cbAnswer.getTag().toString();
String cbAnswerJState = cbAnswerJTag.split("@")[0];
if (cbAnswerJState.equals("1")) { // 0=>unchecked|1=>checked
setCheckBoxUnchecked_TestMode(cbIndex);
cbAnswer.setTag("0@" + cbAnswerJTag.split("@")[1]);
} else {
setCheckBoxChecked_TestMode(cbIndex);
cbAnswer.setTag("1@" + cbAnswerJTag.split("@")[1]);
}
}
}
}
首先,任何时候您以编程方式创建 Views
,您都可能走错了路。您可能希望 RecyclerView
为您执行此操作。另一个巨大的危险信号是您正在使用 getTag()
在 ImageView
中存储信息。无论这些信息是什么,它都应该存储在列表或其他一些数据结构中(可能只是在您已经拥有的 List<AnswerDTO>
中)。
基本上,当您应该首先学习更多核心 Android 概念时,您正在尝试实施 MVVM。以 class 开头,例如 this one.
实际上,您应该告诉视图模型什么事件发生了变化(例如 viewModel.onSelectionChange(itemDataId)
),然后视图模型应该知道它需要更改哪些“数据”以更新视图模型的内部状态, 这应该被视图观察到,通常与数据绑定。
目前您正在为视图模型提供“视图”相关对象 - ImageView
- 它不应直接在视图对象上设置状态,即基于视图模型状态的视图关注点。看起来您只是将视图函数移动到视图模型,但它不属于那里。
像这样:
视图 <-- 数据绑定 --> 视图模型 <------> 模型
或没有数据绑定:
视图 -- 事件 ---> ViewModel <------> 模型
视图<----数据更新---视图模型<------>模型