【问题标题】:How does the Presenter know which Model is manipulated through it's showing View?Presenter 怎么知道哪个 Model 是通过它显示 View 来操作的?
【发布时间】:2016-05-27 19:29:39
【问题描述】:

我已经开始研究关于 Android 框架的 MVP,因为我想开始我未来的一些设计模式的工作,并且我了解到 MVP 非常适合构建 Android 应用程序。

我对 MVP 原则有疑问:

例子是:

我有一个 视图,它有 2 个交互 选项:

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

Presenter 应该在水果被点击 时捕捉事件,计算字母,并调用 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



   }
}

注意:这里的 Model 是一个 String 只是因为为了简化示例,它可以是任何健壮的类。

据我了解,MVP 的原则之一是 Views 对它们所展示的 Model 一无所知。因此,将 Model 实例保存为 View 实例的属性是不行的,然后在需要时(进行交互时)将 Model 实例传递给 Presenter 以执行进一步的业务逻辑。 (数字母)

所以我的问题是在这样的情况下,当 Views 代表一个特定的 Model 实例,演示者如何确切知道哪个 Model 实例正在交互?

如果我误解了什么,请仔细向我详细解释。

(我是从this site那里学到的);

【问题讨论】:

    标签: android design-patterns mvp


    【解决方案1】:

    您将让您的视图通知演示者选择了列表中的哪个位置,然后演示者将从模型中选择正确的水果,然后在视图中设置适当的视图。这是一个简单的人为示例。 (几乎是伪代码)

    假设您有一个视图,其中有一个 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);
    

    然后在 Presenter 中将实现 AdapterView.OnItemClickListener 添加到类定义中并在那里实现监听器。 这样做的缺点是演示者会知道 android View 类,我认为如果视图和演示者通过独立于平台的接口进行通信会更好,所以可能只发送位置可能是最好的。

    【讨论】:

    • 因此视图可以将位置发送回演示者。它是 MVP 使用的适当方式吗?或者它只是一种解决方法?我没有找到任何关于这种方法的在线资源,这就是为什么我发布了一个关于它的问题,你能链接一些资源吗?
    • 我的视图必须报告某些内容,我不确定您是否会找到涵盖该详细程度的任何内容。列表视图是一个显示列表的小部件,可以报告列表中的哪个项目被选中,它不知道被选中的项目是什么,只是知道某个项目被选中。如果你想更“纯粹”,你可以让演示者实现 onItemClickListener,然后在视图中简单地将演示者设置为 onItemClickListener。
    猜你喜欢
    • 1970-01-01
    • 2017-03-14
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多