使用MVP模式来解耦activity中业务代码和界面代码。在activity中,将其中的业务抽象到presenter层;将其中的界面代码抽象到View层。

MVP模式:

一个软件被划分成三层,View层,Presenter层,Model层。

View层的职责是展示界面,界面绘制。

Presenter层的职责是,实现各种业务逻辑,业务逻辑的代码都放在这一层。

Model层的职责是数据的存储,修改,获取。

各层之间的交互:

View层和Presenter层之间的通信是双向的。

Presenter层和Model层之间的通信是双向的。

View层不与Model层发生交互。

MVP模式应用到Android app:

View层:activity,fragment,其中的界面展示,就是View层的内容。

Presenter层:点击一个按钮要执行的业务逻辑,则是由Presenter层来实现。也就是说,Presenter层抽象,提取出activity,fragment中的业务逻辑。这样就可以将业务逻辑代码与界面展示代码解耦掉。可以重用业务逻辑。

Model层:这一层,则是数据存取,数据修改层。配置信息,获取数据源的数据,获取服务器数据,获取数据库的数据,更新数据库的数据,这些实现代码都由这一层来提供。

MVP模式应用到Android app的一个例子分析:

例子分析:
 
1.每个层要做的事情,用接口声明好。
2.接口声明好之后,就用实际的类来实现。
 
比如登陆界面:
1.要确定出登陆界面,它的View有哪些行为。
2.登陆界面的业务逻辑实现,是通过调用presenter层的方法来进行的。
3.presenter与view之间是相互通信的。
 

Login这个模块,把View层和presenter层放在了一起:

package com.antonioleiva.mvpexample.app.Login;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;

import com.antonioleiva.mvpexample.app.R;
import com.antonioleiva.mvpexample.app.main.MainActivity;

public class LoginActivity extends Activity implements LoginView, View.OnClickListener {

private ProgressBar progressBar;
    private EditText username;
    private EditText password;
    private LoginPresenter presenter;

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

progressBar = (ProgressBar) findViewById(R.id.progress);
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
        findViewById(R.id.button).setOnClickListener(this);

presenter = new LoginPresenterImpl(this);
    }

@Override public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);
    }

@Override public void hideProgress() {
        progressBar.setVisibility(View.GONE);
    }

@Override public void setUsernameError() {
        username.setError(getString(R.string.username_error));
    }

@Override public void setPasswordError() {
        password.setError(getString(R.string.password_error));
    }

@Override public void navigateToHome() {
        startActivity(new Intent(this, MainActivity.class));
        finish();
    }

@Override public void onClick(View v) {
        presenter.validateCredentials(username.getText().toString(), password.getText().toString());
    }
}

一、View层和presenter的交互:
 
View到presenter的调用(View--->presenter):
上述代码,当用户点击按钮的时候,会执行一个账号和密码验证的业务逻辑。这个业务逻辑是封装在presenter中的。我们调用presenter的validateCredentials方法,传递参数,就可以执行账号和密码验证的业务逻辑。
 
将业务逻辑封装到presenter层的好处是,我们可以在任何地方重用一个业务逻辑。比如,这个validateCredentials的业务逻辑,就可以被重用。
 
presenter到View的调用(presenter--->view):
在实例化presenter的时候,要提供一个LoginView的实现。
 public LoginPresenterImpl(LoginView loginView) {
        this.loginView = loginView;
        this.loginInteractor = new LoginInteractorImpl();
    }
然后,LoginView接口定义了各种行为。presenter通过调用LoginView提供的行为,来实现presenter对View的控制。
在这里,进行验证的时候,会有不同的情况,针对不同的情况,presenter层会调用LoginView中不同的方法,来告知用户当前的验证结果。
如下:
 @Override public void onUsernameError() {
        loginView.setUsernameError();
        loginView.hideProgress();
    }
 
  @Override public void onPasswordError() {
        loginView.setPasswordError();
        loginView.hideProgress();
    }
 
   @Override public void onSuccess() {
        loginView.navigateToHome();
    }
 
1).presenter层的业务逻辑实现:
Presenter层只有一个业务逻辑,它由接口LoginPresenter接口声明:
public interface LoginPresenter {
    public void validateCredentials(String username, String password);
}
 
public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {

private LoginView loginView;
    private LoginInteractor loginInteractor;

public LoginPresenterImpl(LoginView loginView) {
        this.loginView = loginView;
        this.loginInteractor = new LoginInteractorImpl();
    }

@Override public void validateCredentials(String username, String password) {
        loginView.showProgress();
        loginInteractor.login(username, password, this);
    }

@Override public void onUsernameError() {
        loginView.setUsernameError();
        loginView.hideProgress();
    }

@Override public void onPasswordError() {
        loginView.setPasswordError();
        loginView.hideProgress();
    }

@Override public void onSuccess() {
        loginView.navigateToHome();
    }
}

它的业务逻辑实现是由成员loginInterator来做的。
然后,loginInterator要将判断结果通知LoginPresenterImpl,它通过调用OnLoginFinishedListener的接口中的方法。LoginPresenterImpl实现了OnLoginFinishedListener接口。
 
通信由LoginInteratorImpl到LoginPresenterImpl(LoginInteratorImpl--->LoginPresenterImpl):
OnLoginFinishedListener接口,定义了LoginPresenterImpl可以被LoginInteratorImpl调用的行为,用来告知LoginPresenterImpl验证的结果。
public interface OnLoginFinishedListener {

public void onUsernameError();

public void onPasswordError();

public void onSuccess();
}

 
public class LoginInteractorImpl implements LoginInteractor {

@Override
    public void login(final String username, final String password, final OnLoginFinishedListener listener) {
        // Mock login. I'm creating a handler to delay the answer a couple of seconds
        new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                boolean error = false;
                if (TextUtils.isEmpty(username)){
                    listener.onUsernameError();
                    error = true;
                }
                if (TextUtils.isEmpty(password)){
                    listener.onPasswordError();
                    error = true;
                }
                if (!error){
                    listener.onSuccess();
                }
            }
        }, 2000);
    }
}  

通信由LoginPresenterImpl到LoginInteratorImpl(LoginPresenterImpl--->LoginInteratorImpl):
    @Override public void validateCredentials(String username, String password) {
        loginView.showProgress();
        loginInteractor.login(username, password, this);
    }
 
二、View层:
当前的Activity实现了LoginView接口,那么当前Activity是是LoginView,作为View层。
它定义了供presenter调用的行为。
public interface LoginView {
    public void showProgress();

public void hideProgress();

public void setUsernameError();

public void setPasswordError();

public void navigateToHome();
}

---------------------------------------------------------------------
Main模块
 
 
一、View层:
public interface MainView {

public void showProgress();

public void hideProgress();

public void setItems(List<String> items);

public void showMessage(String message);
}

这些是供presenter层调用的方法。
这些方法中的代码是跟界面展示有关的。
 
View层到Presenter层的通信,及View层的实现:
public class MainActivity extends Activity implements MainView, AdapterView.OnItemClickListener {

private ListView listView;
    private ProgressBar progressBar;
    private MainPresenter presenter;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.list);
        listView.setOnItemClickListener(this);
        progressBar = (ProgressBar) findViewById(R.id.progress);
        presenter = new MainPresenterImpl(this);

}

@Override protected void onResume() {
        super.onResume();
        presenter.onResume();
    }

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

@Override public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);
        listView.setVisibility(View.INVISIBLE);
    }

@Override public void hideProgress() {
        progressBar.setVisibility(View.INVISIBLE);
        listView.setVisibility(View.VISIBLE);
    }

@Override public void setItems(List<String> items) {
        listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));
    }

@Override public void showMessage(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        presenter.onItemClicked(position);
    }
}

 
红色部分是MainView的行为,都是界面展示方面的代码。
蓝色部分,是View层到Presenter通信的实现(View--->Presenter)。
 
二、Presenter层:
public interface MainPresenter {

public void onResume();

public void onItemClicked(int position);
}

它有两个业务逻辑要实现,一个是onResume(),一个是onItemClicked(int position)。
 
Presenter层到View层的通信,及Presenter层的实现:
public class MainPresenterImpl implements MainPresenter, OnFinishedListener {

private MainView mainView;
    private FindItemsInteractor findItemsInteractor;

public MainPresenterImpl(MainView mainView) {
        this.mainView = mainView;
        findItemsInteractor = new FindItemsInteractorImpl();
    }

@Override public void onResume() {
        mainView.showProgress();
        findItemsInteractor.findItems(this);
    }

@Override public void onItemClicked(int position) {
        mainView.showMessage(String.format("Position %d clicked", position + 1));
    }

@Override public void onFinished(List<String> items) {
        mainView.setItems(items);
        mainView.hideProgress();
    }
}

红色部分是Presenter层到View层的通信实现(Presenter--->View)。
onResume()方法和onItemClicked(int position)方法是Presenter实现的业务逻辑。
其中FindItemsInteractor成员,负责创建一个List的实现。
 
参考资料:
 http://antonioleiva.com/mvp-android/

MVP应用在android app上的更多相关文章

  1. 将TensorFlow训练好的模型迁移到Android APP上(TensorFlowLite)

    转自:https://blog.csdn.net/u012328159/article/details/81101074 https://blog.csdn.net/masa_fish/article ...

  2. Android App的架构设计:从VM、MVC、MVP到MVVM

    随着Android应用开发规模的扩大,客户端业务逻辑也越来越复杂,已然不是简单的数据展示了.如同后端开发遇到瓶颈时采用的组件拆分思想,客户端也需要进行架构设计,拆分视图和数据,解除模块之间的耦合,提高 ...

  3. ANDROID – TOOLBAR 上的 NAVIGATION DRAWER(转)

    在 Material Design 釋出後,Google 也開始陸續更新了 Google app 的介面,讓大家有個範例可以看.而過去大力推動的 actionbar 自然而然也成了眾開發者觀注的部份: ...

  4. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...

  5. Android App的设计架构:MVC,MVP,MVVM与架构AAAAA

    1. 架构设计的目的1.1 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.1.2 这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续 ...

  6. android app崩溃日志收集以及上传

    源代码获取请到github:https://github.com/DrJia/AndroidLogCollector 已经做成sdk的形式,源代码已公开,源代码看不懂的请自行google. 假设想定制 ...

  7. Android 开发 关于APP无法安装到Android模拟器上的问题

    我们在创建一个app后,打算安装到Android模拟器上.可能会出现无法安装,或者提示已经安装无法卸载的问题.这个时候需要添加兼容CPU. 选择 build.gradle 文件打开添加如下代码: an ...

  8. Android APP架构设计——MVP的使用示例

    0. 前言 为了更好地进行移动端架构设计,我们最常用的就是MVC.MVP和MVVM,作为三个最耳熟能详的三大架构,应用可谓非常广泛.对于这三种架构设计以及优缺点已经在Android APP架构设计-- ...

  9. [转]Android App整体架构设计的思考

    1. 架构设计的目的 对程序进行架构设计的原因,归根到底是为了提高生产力.通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点, ...

随机推荐

  1. 原生javascript自定义input[type=radio]效果

    2018年6月27日 更新 找到最为简单的仅仅使用css3的方案 <!DOCTYPE html> <html lang="en"> <head> ...

  2. Apriori算法详解

    一.Apriori 算法概述Apriori 算法是一种最有影响力的挖掘布尔关联规则的频繁项集的 算法,它是由Rakesh Agrawal 和RamakrishnanSkrikant 提出的.它使用一种 ...

  3. Python实现FTP服务功能

    本文从以下三个方面, 阐述Python如何搭建FTP服务器 一. Python搭建FTP服务器 二. FTP函数释义 三. 查看目录结构 四. 上传下载程序 一. Python搭建FTP服务器 1. ...

  4. SFTPHelper

    public class SFTPHelper { #region 字段或属性 private readonly SftpClient _sftp; /// <summary> /// S ...

  5. array to object

    array to object native js & ES6 https://stackoverflow.com/questions/4215737/convert-array-to-obj ...

  6. asp.netMVC中实现分页方法

    方法一:使用传统的sql语句实现分页,    public class UserprintDao如下 /// <summary> /// 取得用户申请记录列表(按分页) /// </ ...

  7. asp.net mvc4 使用分部视图来刷新数据库

    前几天研究SSE,用浏览器做侦听后台数据库数据变化,如果有更新,就即时通过浏览器,使用SSE效果果然OK,侦听数据库有更新时马上会向浏览器通知有新数据,我还在浏览器里放了短音提示,但遇到一个问题,发出 ...

  8. 【Python】python学习之总结

    迭代器: def gen(): a = yield a a = a * yield a for i in gen(): print(i) 创建一个函数,循环体,yield循环到此就返回一个值.调用函数 ...

  9. BZOJ 1797 最小割(最小割割边唯一性判定)

    问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断? 现在请你回答这两个问题. 最小割唯一性判定 jcvb: 在残余网络上跑ta ...

  10. Json-转自菜鸟教程

    1. python中为什么用json有什么作用??不是python用json,json是类似xml的一种通用格式,在很多地方都可以用.json相比xml,数据量更小,而且可以很方便的和解释型语言的结构 ...