app架构学习之MVP

App有一个好的架构,它可以带来如下的好处:容易扩展;容易维护。如果一个App没有一个好的架构,那么,耦合的代码会到处出现。没有一个架构,那么,代码会是各种混乱,我深有体会。

混乱,看起来问题不大,对于小规模的app,因为,我始终还是可以花时间读懂它。但是,随着app的功能越来越多,那么,你每次添加一个功能或者修改一个功能的时候,你会发现:1.你做的功能和之前做的功能,有重复代码。2.你难以快速完好,正确的修改一个功能,因为代码过于耦合,因为代码层次不清楚。

总之,过去的经验告诉我,要对一个App进行架构,划分好层次,然后,按照定义好的架构模式去开发,这可以带来好处。我在确定了架构的重要性之后,那么接下来当然是学习它。

我今天学习的架构模式是MVP。

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/

时间: 2024-10-17 17:42:47

app架构学习之MVP的相关文章

安卓实战之如何快速搭建app架构

前言 最近公司的另一个项目又要立项了,作为公司的唯一安卓工程师任务来了(新来的移动端的老大说项目还是主要你负责,我就负责帮你们安排下进度),听了这话我是伤心的在这公司不管是几个还是1个安卓开发都是我来搭建,干着与工资不符的事情,好的一点是开发没有人干涉平时也能学习自己想学的东西. 如何选择app架构(MVC/MVP/MVVM) 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解MVP,但是还是觉得比较牛逼,然后呢也想在公司的项目中去使用它. 项目时间紧迫:快速开

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

来源: Android App的设计架构:MVC,MVP,MVVM与架构经验谈 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于App的架构如何设计: 我的App需要应用这些设计架构吗? MVC,MVP等架构讲的是什么?区别是什么? 本文就来带你分析一下这几个架构的特性,优缺点,以及App架构设计中应该注意的问题. 1.架构设计的目的 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员

Android APP架构心得

前言 从JavaEE转到Android开发也2年多了,开发的项目也有4,5个了(公司项目),其中有3个项目前期都是自己独立开发,从一开始的毫无架构到现在对如何架构也有一点心得,所以在此分享出来,大家一起交流 什么是架构 在我看来,软件架构绝对不只是框架的堆砌,看我看来,架构是为了方便软件维护.扩展.安全性.切入性(我也不知道有没有人提出过这个关键字,因为的确很少看见,简单来说我这里说的切入性就是指一个以前没有接触过这个项目的人,能快速加入到这个项目中,对项目进行维护.修改和扩展) 维护性 一个好

Google App Engine 学习和实践

这个周末玩了玩Google App Engine,随手写点东西,算是学习笔记吧.不当之处,请多多指正. 作者:liigo,2009/04/26夜,大连 原创链接:http://blog.csdn.net/liigo/archive/2009/04/26/4127055.aspx 转载请注明出处:http://blog.csdn.net/liigo 一,怎么想起来玩Google App Engine了呢? 近期想写一个小程序,以便在公司的电脑和家里的电脑之间随时共享数据.但是没有现成的server

【转载】安卓APP架构

注:本篇博文转载于 http://my.oschina.net/mengshuai/blog/541314?fromerr=z8tDxWUH 本文介绍了文章作者从事了几年android应用的开发,经历2次架构变革,第一次集成了RxJava第二次集成了MVP,并将RxJava与MVP完美结合,实现了低耦合,代码简单,测试方便的架构. 其实我们在开发中也遇到过,Android入门门槛较低,如果前期对APP规划不清晰,Coder们对未来变化把握不准,技术架构经验不够强大,最终导致就是一个Activit

Android 网络通信架构学习

最近跟着云课堂上的极客学院做安卓APP,学习了课程里面介绍的一种网络通信架构.清晰明了,比我自己东一块西一块拼凑出来的要好很多.在这里记录一下. 云课堂的连接:http://study.163.com/course/courseMain.htm?courseId=917001 目录: 一.Android端实现 1.1 架构图 1.2 NetworkConnection.java实现 1.3 Logic.java实现 1.4 Activity.java实现 二.测试 2.1 服务器配置 2.2 结

MVP架构-Android官方MVP项目和响应式MVP-RxJava项目架构分析对比解读

介绍 MVP这个架构一直是Android开发社区讨论的焦点,每个人都有自己的分析理解众说纷纭.直到GitHub上Google官方发布用MVP架构搭建的项目.感觉是时候分析了. MVP架构简介 这不是本文重点,所以摘抄自李江东的博文 MVP架构简介 对于一个应用而言我们需要对它抽象出各个层面,而在MVP架构中它将UI界面和数据进行隔离,所以我们的应用也就分为三个层次. View:对于View层也是视图层,在View层中只负责对数据的展示,提供友好的界面与用户进行交互.在Android开发中通常将A

App架构师成长路线

点击关注 异步图书,置顶公众号 每天与你分享 IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书 --异步小编 架构师,软件技术领域一个高大上的名词,业界有言"人人都是产品经理",却很少听到"人人都是架构师".其本身涉及的复杂庞大的跨领域知识体系除外,对于架构一词,其实很难去完整地定义,我们也没必要过于纠结,就如我们为什么要登山,因为山在那里,执着前行,或许还未曾知晓路在何方,抑或你都不曾思考要去何方,但至少你已经在路上,while(!(succeed

BAT大厂APP架构演进实践与优化之路

第1章 打车课程项目整体介绍课程介绍:介绍课程内容.教授方式,讲诉打车业务的整体架构思路:针对打车业务如何进行需求分析和工作量化评估,同时根据工作量化提出课程内容章节计划.1-1 lesson01-课程整体介绍导学 第2章 需求分析和工作量化讲解(在BAT大厂中)前后端 API .文档维护方法.平台.2-1 lesson02-需求分析与工作量化 第3章 项目规范与团队协作分享在BAT大厂中.项目支持是如何维护.保证代码质量的.然后实践,建立滴滴打车项目的代码规范.约定.3-1 lesson03-