Android MVP 模式应用实例

转载请注明来源: http://blog.csdn.net/kjunchen/article/details/52698186

Android MVP 模式应用实例解析

概述

MVPModel - View - Presenter。 Model 提供数据,View 负责显示,Presenter 负责逻辑处理。

  • View: 对应于 Activity , 负责 View 的绘制以及用户交互。

  • Model: 依然是业务逻辑和实体模型

  • Presenter: 负责完成 View 和 Modle 之间的交互

The MVP pattern stands for Model-View-Presenter, and it separates the UI concerns between the data of the UI (Model), the display of the UI (View), and the logic of the UI (Presenter). For Android, the View is the Activity, which will handle gathering user input and updating the display; the Presenter is a class that will handle communication between the Model and View; the Model will handle persisting and retrieving data, along with any business logic that the data must adhere to. Interfaces will be used to de-couple each of these components.

单一职责原则(SRP:Single responsibility principle)又称单一功能原则

MVP 优点

  • 分离了视图逻辑和业务逻辑,降低了耦合

  • Activity 只处理生命周期的任务,代码变得更加简洁

  • 试图逻辑和业务逻辑分别抽象到了 View 和 Presenter 的接口中,提高代码阅读性

  • Presenter 抽象成接口,可以有多种具体的实现,方便进行单元测试

  • 将业务逻辑抽到 Presenter 中,避免后台线程引用 Activity 导致 Activity 的资源无法被系统回收从而引起内存泄露和 OOM

MVP 设计技巧

先设计 View 和 Model,最后设计 Presenter 。

View 主要是定接口,有些情况下没有 Model 。

Sample

理论需要付诸实践,下面就来写个 MVP 模式应用的示例,看看在项目中具体如何应用,如何将 View 与 Model 进行完美分离,而采用 Presenter 进行交互。下面举个加载保存用户的例子:

项目整体结构图:

效果图:

View

View 中主要设计接口,只做 UI 显示相关的。

public interface ICustomerView {
    void setCustomerId(int id);
    void setCustomerFirstName(String firstName);
    void setCustomerLastName(String lastName);
    int getCustomerId();
    String getCustomerFirstName();
    String getCustomerLastName();
    void showSaveResult(String result);
    void showLoadFailedInfo();
}

Model

Model 中设计数据模型,提供 UI 显示需要的数据内容。

首先我们需要一个实体对象 Customer :

public class Customer {
    private int id;
    private String firstName;
    private String lastName;

    //Omit to write set and get method
    ...
}

接着在设计一个 Customer 的接口 ICustomerModel ,这里面主要是 保存和加载用户:

public interface ICustomerModel {
    boolean saveCustomer(String firstName, String lastName);
    Customer loadCustomer(int id);
}

最后实现接口:

public class CustomerModel implements ICustomerModel {
    @Override
    public boolean saveCustomer(String firstName, String lastName) {
        return true;
    }

    @Override
    public Customer loadCustomer(int id) {
        Customer customer = new Customer();
        customer.setFirstName("Junk");
        customer.setLastName("Chen");
        return customer;
    }
}

Presenter

设计完 View 和 Model 后,就可以设计 Presenter ,它主要是完成 View 与 Model 之间的交互、数据传递。在 Presenter 中会获得 View 的引用,实例化 Model 。

这里我依然是先设计了一个 ICustomerPresenter 接口,定义了 保存和加载用户的两个方法:

public interface ICustomerPresenter {
    void saveCustomer(final String firstName, final String lastName);
    void loadCustomer(final int id);
}

然后我实现这个接口:

public class CustomerPresenterImpl implements ICustomerPresenter {
    private static final String TAG = "CustomerPresenterImpl";
    private ICustomerModel customerModel;
    private ICustomerView customerView;

    public CustomerPresenterImpl(ICustomerView customerView) {
        this.customerView = customerView;
        customerModel = new CustomerModel();
    }

    @Override
    public void saveCustomer(final String firstName, final String lastName) {
        if (firstName.isEmpty() || lastName.isEmpty()) {
            customerView.showSaveResult("first name or last name can't empty");
            return;
        }
        boolean isSaveSuccess = customerModel.saveCustomer(firstName, lastName);
        if (isSaveSuccess)
            customerView.showSaveResult("Save success");
        else
            customerView.showSaveResult("Save failed");
    }

    @Override
    public void loadCustomer(final int id) {
        if (id > 0) {
            Customer customer = customerModel.loadCustomer(id);
            customerView.setCustomerFirstName(customer.getFirstName());
            customerView.setCustomerLastName(customer.getLastName());
        } else {
            customerView.showLoadFailedInfo();
            customerView.setCustomerFirstName("");
            customerView.setCustomerLastName("");
        }
    }
}

Activity

最后看看我们的 Activity 到底是什么样的呢?在 Activity 中会实例化 CustomerPresenterImpl 。

public class CustomerActivity extends AppCompatActivity implements ICustomerView, View.OnClickListener {
    private static final String TAG = "CustomerActivity";
    private EditText edt_id, edt_firstName, edt_lastName;
    private Button btn_saveCustomer, btn_loadCustomer;

    private ICustomerPresenter mCustomerPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_customer);

        initView();
        mCustomerPresenter = new CustomerPresenterImpl(this);
    }

    private void initView() {
        edt_id = (EditText) findViewById(R.id.edt_id);
        edt_firstName = (EditText) findViewById(R.id.edt_firstName);
        edt_lastName = (EditText) findViewById(R.id.edt_lastName);
        btn_saveCustomer = (Button) findViewById(R.id.btn_saveCustomer);
        btn_loadCustomer = (Button) findViewById(R.id.btn_loadCustomer);

        btn_saveCustomer.setOnClickListener(this);
        btn_loadCustomer.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_saveCustomer: {
                mCustomerPresenter.saveCustomer(getCustomerFirstName(), getCustomerLastName());
                break;
            }
            case R.id.btn_loadCustomer: {
                mCustomerPresenter.loadCustomer(getCustomerId());
                break;
            }
        }
    }

    @Override
    public void setCustomerId(int id) {
        edt_id.setText(String.valueOf(id));
    }

    @Override
    public void setCustomerFirstName(String firstName) {
        edt_firstName.setText(firstName);
    }

    @Override
    public void setCustomerLastName(String lastName) {
        edt_lastName.setText(lastName);
    }

    @Override
    public int getCustomerId() {
        if (edt_id.getText().toString().isEmpty()) return 0;
        return Integer.parseInt(edt_id.getText().toString());
    }

    @Override
    public String getCustomerFirstName() {
        return edt_firstName.getText().toString();
    }

    @Override
    public String getCustomerLastName() {
        return edt_lastName.getText().toString();
    }

    @Override
    public void showSaveResult(String result) {
        Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showLoadFailedInfo() {
        Toast.makeText(this, "No customer.", Toast.LENGTH_SHORT).show();
    }
}

可以看到在 Activity 中只是做与 UI 显示有关的事情,需要数据就去找 Presenter 。

可以看到整个项目结构非常清晰,易理解。示例简单,抛砖引玉。

欢迎加QQ群交流: 365532949
Homepage: http://junkchen.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,让我给您举一个 Android MVP 框架实例。 假设我们要开发一个简单的登录界面,包含一个用户名输入框、一个密码输入框和一个登录按钮。我们可以按照 MVP 框架的方式来组织代码。 首先,我们定义一个 View 接口,包含了用户界面的一些方法,例如显示错误信息、显示登录成功等。 ```java public interface LoginView { void showProgress(); void hideProgress(); void setUsernameError(); void setPasswordError(); void navigateToHome(); } ``` 然后,我们定义一个 Presenter 接口,包含了处理用户输入的一些方法,例如验证用户名密码、进行登录等。 ```java public interface LoginPresenter { void validateCredentials(String username, String password); void onDestroy(); } ``` 接下来,我们实现 Presenter 接口,并在其中处理逻辑。 ```java public class LoginPresenterImpl implements LoginPresenter { private LoginView view; public LoginPresenterImpl(LoginView view) { this.view = view; } @Override public void validateCredentials(String username, String password) { if (TextUtils.isEmpty(username)) { view.setUsernameError(); return; } if (TextUtils.isEmpty(password)) { view.setPasswordError(); return; } // 调用模型层的方法验证用户名密码 boolean isValid = UserModel.validateUser(username, password); if (isValid) { view.showProgress(); view.navigateToHome(); } else { view.hideProgress(); view.setUsernameError(); view.setPasswordError(); } } @Override public void onDestroy() { view = null; } } ``` 最后,我们实现 Activity 中的 View 接口,并将 Presenter 和 View 进行绑定。 ```java public class LoginActivity extends AppCompatActivity implements LoginView { private EditText etUsername; private EditText etPassword; private Button btnLogin; private ProgressBar progressBar; private LoginPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); etUsername = findViewById(R.id.et_username); etPassword = findViewById(R.id.et_password); btnLogin = findViewById(R.id.btn_login); progressBar = findViewById(R.id.progress_bar); presenter = new LoginPresenterImpl(this); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String username = etUsername.getText().toString(); String password = etPassword.getText().toString(); presenter.validateCredentials(username, password); } }); } @Override public void showProgress() { progressBar.setVisibility(View.VISIBLE); } @Override public void hideProgress() { progressBar.setVisibility(View.GONE); } @Override public void setUsernameError() { etUsername.setError("用户名不能为空"); } @Override public void setPasswordError() { etPassword.setError("密码不能为空"); } @Override public void navigateToHome() { Intent intent = new Intent(this, HomeActivity.class); startActivity(intent); finish(); } @Override protected void onDestroy() { super.onDestroy(); presenter.onDestroy(); } } ``` 以上就是一个简单的 Android MVP 框架实例,其中 View 接口定义了用户界面的一些方法,Presenter 接口定义了处理用户输入的一些方法,Presenter 实现了 Presenter 接口中的方法并在其中处理逻辑,Activity 实现了 View 接口中的方法并将 Presenter 和 View 进行了绑定。通过这种方式,我们可以将不同层的代码分离开来,使得代码更加清晰、易于维护和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Junk Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值