讲Android mvp模式的书,Android MVP模式学习

72ffc68d0457?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

MVP简介

随着时代的发展,移动端UI越来越丰富、业务越来越复杂,用户对界面的美观、渲染的速度、数据读取的速度要求也越来越高。为了在保证拥有酷炫的UI、复杂的业务逻辑的条件下给用户更好的体验,需要对view、model、controller职责进行细分,让view专注于处理数据的可视化以及和用户的交互、让model专注于数据的处理。一种新的模式MVP(Model - View - Presenter)应运而生。

MVP和MVC的差异

MVP模式是从MVC模式理念的基础上衍生出来的,在MVC的基础上对V和M进行了绝对的解耦,两者之间只有通过Presenter才能通信,优化了V层和C层,职责划分更明确、单一。MVC中,M层和V层是可以通信的,MVP中M层和V层是完全隔离的,只能通过P层来通信,如图(这里借图一用)。

72ffc68d0457?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

在MVC模式时期,由于UI越来越丰富、逻辑处理越来越复杂,Activity中对UI的活动展示以及和用户的交互也越来越复杂,代码量比较大,同时受限于Android的线程安全以及很多时候需要使用到Activity的生命周期,我们有不少的Controller层的代码也会写在Activity里面,也就是Activity同时承担了View层和部分Controller层的工作,影响开发效率,不利于维护和扩展。

于是,我们将复杂的逻辑移至另外一个类Presenter,让Activity只负责UI的展示以及和用户的交互。View层,创建View Interface,定义好View层的活动事件,Activity加载布局、实现View Interface,将View Interface传入Presenter实例,通过View Innterface和Presenter实现交互;Model层,负责存储、检索、操纵数据,可以通过创建一个Model Interface来进一步实现解耦;Presenter层,作为View和Model交互的中间枢纽,负责接收用户操作,调用Model层,将数据反馈到View层展示给用户。

选择MVP的必要性

1)降低了耦合性;

2)各模块职责划分明确,利于协同开发;

3)业务逻辑独立出来,通过接口调用,方便单元测试;

4)代码重用性高;

示例

这里跟随很多大牛的脚步,同样使用登录页面来作为第一次体验MVP的示例。

①登录页面布局activity_main.xml代码,布局比较简单,两个输入框,一个登录按钮,一个加载等待条(默认隐藏)。

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".LoginActivity"

android:padding="20dp">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical"

android:layout_centerVertical="true"

>

android:id="@+id/userName"

android:layout_width="match_parent"

android:layout_height="50dp"

android:hint="用户名"/>

android:id="@+id/password"

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_marginTop="5dp"

android:hint="密码"/>

android:id="@+id/loginBtn"

android:layout_width="match_parent"

android:layout_height="60dp"

android:layout_marginTop="10dp"

android:text="Login"/>

android:id="@+id/progressBar"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:visibility="gone"/>

②View Interface,这里定义的是View的活动,这里登录页面存在的活动有(显示加载等待框、隐藏加载等待框、返回登录成功或者登录失败),所以ILoginView代码如下。

public interface ILoginView {

/*显示等待框*/

void showProgress();

/*隐藏等待框*/

void hideProgress();

/*登录成功*/

void loginSuccess();

/*登录失败*/

void loginError();

}

③Model Interface,需要在model中去判断用户名和密码是否正确,并返回处理结果,所以ILoginModel需要定义一个checkLogin方法,再定义一个回调的内部接口,因为只有P能主动通信M,M不能主动通信P,所有这里采用回调来返回结果。

public interface ILoginModel {

/*回调接口*/

interface OnLoginListener{

/*登录成功回调*/

void loginSuccess();

/*登录失败回调*/

void loginError();

}

/*判断输入的用户名、密码,调用内部接口回调*/

void checkLogin(String userName,String password,OnLoginListener listener);

}

④实现ILoginModel,这里虚拟登录。

public class LoginModelImpl implements ILoginModel {

@Override

public void checkLogin(final String userName, final String password,

final OnLoginListener listener) {

new Handler().postDelayed(new Runnable() {

@Override

public void run() {

if(userName.equals("1") && password.equals("1")){

listener.loginSuccess();

}else{

listener.loginError();

}

}

},3000);

}

}

⑤Presenter Interface,Presenter接收用户点击按钮的事件,然后调用Model处理数据,ILoginPresenter需要toLogin方法。

public interface ILoginPresenter {

void toLogin(String userName,String password);

}

⑥实现Presenter,P层作为V和M的交互媒介,需要同时持有V和M,在M处理完返回的时候还需要通知到V层,所以还要实现M层的回调接口。由于V层可以主动沟通P层,所以V层和P层互相持有,这里V层直接在构造函数里传递过来。

public class LoginPresenterImpl implements ILoginPresenter,

ILoginModel.OnLoginListener {

private ILoginView mView;

private ILoginModel mModel;

public LoginPresenterImpl(ILoginView iLoginView) {

mView = iLoginView;

mModel = new LoginModelImpl();

}

@Override

public void toLogin(String userName, String password) {

mView.showProgress();

mModel.checkLogin(userName,password,this);

}

@Override

public void loginSuccess() {

mView.hideProgress();

mView.loginSuccess();

}

@Override

public void loginError() {

mView.hideProgress();

mView.loginError();

}

}

⑦View实现加载,这里在Acitvity中操作,实现View Interface,实例化Presenter,将View Interface作为参数传递给Presenter。

package liu.wolf.firstmvpdemo;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ProgressBar;

import android.widget.Toast;

import liu.wolf.firstmvpdemo.presenter.LoginPresenterImpl;

import liu.wolf.firstmvpdemo.view.ILoginView;

public class LoginActivity extends AppCompatActivity implements

ILoginView{

private ProgressBar progressBar;

private EditText userName,password;

private Button loginBtn;

private LoginPresenterImpl mPresenter = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mPresenter = new LoginPresenterImpl(this);

progressBar = findViewById(R.id.progressBar);

userName = findViewById(R.id.userName);

password = findViewById(R.id.password);

loginBtn = findViewById(R.id.loginBtn);

loginBtn.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

mPresenter.toLogin(userName.getText().toString(),

password.getText().toString());

}

});

}

@Override

public void showProgress() {

progressBar.setVisibility(View.VISIBLE);

}

@Override

public void hideProgress() {

progressBar.setVisibility(View.GONE);

}

@Override

public void loginSuccess() {

Toast.makeText(LoginActivity.this,"登录成功!",

Toast.LENGTH_LONG).show();

}

@Override

public void loginError() {

Toast.makeText(LoginActivity.this,"登录失败!",

Toast.LENGTH_LONG).show();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值