我已开始在Android框架上学习 MVP ,因为我想在一些设计模式中开始我未来的工作,并且我读到MVP非常适合构建Android应用程序。
我对 MVP 原则有疑问:
示例是:
我有一个查看,其中包含 2个互动选项:
演示者应该在点击水果时捕捉事件,计算字母数量,并调用View的打印功能。
使用MVP我尝试了这种方法:
我的观点:
public class MainActivity extends Activity implements MainView, View.OnClickListener {
ViewGroup fruitsContainer;
Button listFruitsBtn;
MyPresenter myPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Making my presenter, its only parameter is a MainView, this MainView.
myPresenter = new MyPresenter(this);
fruitsContainer = (ViewGroup) findViewById(R.id.fruitsContainer);
listFruitsBtn = (Button) findViewById(R.id.list_fruits_btn);
listFruitsBtn.setOnClickListener(this);
}
/**
* Showing fruits, making a TextView for each.
*/
@Override
public void showFruits(List<String> fruits) {
fruitsContainer.removeAllViews();
for (String fruit : fruits) {
TextView textView = new TextView(this);
textView.setText(fruit);
//Question part 1: How does the presenter will know WHICH fruit is clicked?
textView.setOnClickListener(this);
fruitsContainer.addView(textView);
}
}
/**
* When user clicks on the "show fruits" button, the view calls for presenter to take action.
*/
@Override
public void onClick(View v) {
if (v.equals(listFruitsBtn)) {
myPresenter.fruitButtonClicked();
}
else if(v instanceof TextView)
{
TextView textView = (TextView) v;
//Question part 2: How does the presenter will know WHICH fruit is clicked?
//In theory this operation is forbidden as far as I know.
//MVP does not supports views to know anything about the Model that they are showing.
myPresenter.fruitIsClicked(textView.getText().toString());
}
}
}
我的演示者:
public class MyPresenter {
MainView mainView;
public MyPresenter(MainView mainView) {
this.mainView = mainView;
}
/**
* Got a callback for "show fruits" event invoked
* so we call the mainView's showFruits function with the model's data parameter
*/
public void fruitButtonClicked() {
this.mainView.showFruits(MyModel.getFruitsList());
}
//In theory this operation is forbidden as far as I know.
//MVP does not supports views to know anything about the Model that they are showing.
public void fruitIsClicked(String fruit) {
//Clicked operation - counting letters - call print operation of myView
}
}
注意:模型是 String ,这只是因为为了简化示例,它可以是任何健壮的类。
我理解MVP的原则之一 Views对模型一无所知。因此,不能将Model实例保存为View实例的属性,稍后在需要时(在进行交互时)将Model实例传递给Presenter以执行进一步的业务逻辑。 (计数字母)
所以我的问题是在这样的情况下,当视图代表一个特定的模型实例时,演示者如何准确地知道哪个模型实例正在进行交互?
如果我误解了某些内容,请注意向我详细解释。
(我从this site学到了);
答案 0 :(得分:0)
您可以让视图通知演示者选择列表中的哪个位置,然后演示者将从模型中选择正确的水果,然后在视图中设置适当的视图。这是一个快速设计的例子。 (几乎是伪代码)
假设您有一个视图,其中包含用于显示水果列表的ListView(mList),用于显示所选水果的精美图片的ImageView(mImage),以及用于显示所选水果的描述的TextView(mText)选择了水果。
您可以为mList设置一个on item侦听器来报告何时选择一个项目,所以在您的视图类中这样的内容:
mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mPresenter.onItemSelected(position);
}
});
public void setText(String text) {
mText.text = text;
}
public void setImage(...) {
}
然后在您的演示者类中,您将拥有一个onItemSelected方法,该方法从您的模型(水果列表)中收集所需的值并在视图中设置小部件
public void onItemSelected(int position) {
Fruit fruit = model.getFruitAt(position);
view.setText(fruit.getText());
view.setImage(fruit.getImage();
}
更新: 另一种方法是让演示者实现AdapterView.OnItemClickListener接口,并在视图中分配演示者。
所以在视图中就是这样。
mList.setOnItemClickListener(mPresenter);
然后在演示者中将实现AdapterView.OnItemClickListener添加到类定义并在那里实现侦听器。 这方面的缺点是主持人会知道android视图类,我认为如果视图和演示者通过独立于平台的界面进行通信会更好,所以可能只是发送位置可能是最好的。