演示者如何通过显示视图来了解哪个模型被操纵?

时间:2016-02-16 13:27:57

标签: android design-patterns mvp

我已开始在Android框架上学习 MVP ,因为我想在一些设计模式中开始我未来的工作,并且我读到MVP非常适合构建Android应用程序。

我对 MVP 原则有疑问:

示例是:

我有一个查看,其中包含 2个互动选项:

  • 首先列出屏幕上的项目,例如:fruits。
  • 第二个是当列出水果时,用户可以点击它,它应该打印出单词中的字母数

演示者应该在点击水果时捕捉事件,计算字母数量,并调用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学到了);

1 个答案:

答案 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视图类,我认为如果视图和演示者通过独立于平台的界面进行通信会更好,所以可能只是发送位置可能是最好的。