本文是这几天学习的总结,大神别看了,像我一样没用过几次的新司机可以看一下并指正错误。
MVP介绍: 简单明了的理解:P-Presenter:主持者,担当了信息传递的指挥者(同MVC的C);V-View :负责视图的控制:获取界面的数据,为界面加载数据,弹出Toast、跳转界面等(入行以来,我直接把activity作为V层,总觉得这样不妥,今天终于明白了);Model : 与MVC一样数据数据模型,展示数据结构,但是通过这几天的学习,我发现老司机们都把数据处理的代码归于M层,这也是与MVC不同的,没有把数据处理放到P层进行判断而是传到了M层;
逻辑路线(开车了,注意系好安全带): 结合代码讲解,先看一下导航
,,知道路就开车了 呜呜呜呜呜~
今天我就一反常态,大神们写的都是从分支到主干放代码,我就用逆向思维放代码吧,需要实现的接口什么的就紧随其后。
这是登录界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.czh.demo_mvp.LoginActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="35dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/act_login_userid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:inputType="textVisiblePassword"
android:text="q" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="20dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/act_login_userpwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:inputType="textWebPassword"
android:text="q" />
</LinearLayout>
<Button
android:id="@+id/logbtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录" />
</LinearLayout>
这是activity
package com.czh.demo_mvp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.czh.demo_mvp.presenter.LoginPresenter;
import com.czh.demo_mvp.view.LoginView;
import butterknife.BindView;
import butterknife.ButterKnife;
public class LoginActivity extends Activity implements LoginView, View.OnClickListener {
@BindView(R.id.act_login_userid)
EditText act_login_userid;
@BindView(R.id.act_login_userpwd)
EditText act_login_userpwd;
@BindView(R.id.logbtn)
Button logbtn;
private LoginPresenter loginPresenter;
private String tag = "tag";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
loginPresenter = new LoginPresenter(this);
logbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loginPresenter.login();
}
});
}
@Override
public void toIndex() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
@Override
public void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override
public String getName() {
Log.i(tag, "用户名 : " + act_login_userid.getText().toString().trim());
return act_login_userid.getText().toString().trim();
}
@Override
public String getPass() {
Log.i(tag, "密码 : " + act_login_userpwd.getText().toString().trim());
return act_login_userpwd.getText().toString().trim();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
// case R.id.logbtn:
// Log.i(tag, "点击登录");
// loginPresenter.login();
// break;
}
}
}
在act中实现了V层接口,为了与act交互数据,做到了视图操作与activity的解耦
/**
* 处理视图
* Created by Administrator on 2016/6/8.
*/
public interface LoginView {
void toIndex();//跳转页面
//提示信息
void showToast(String msg);
// 获取用户名
String getName();
//获取密码
String getPass();
}
以上的line37 调用了P层的登录操作 见如下line21 ,line21 的登录函数 ,又调用了act中重写的V层的方法,使用V层来获取数据 完美的解耦,并触发M层的观察者模式OnMyLoginListenr。。
line24 调用M层的登录函数(说实话这个我做的不妥,将P层和M层的登录函数用了相同的函数名..),将登录信息传到了M层(实际开发中,M层应该会将数据封装对象),
package com.czh.demo_mvp.presenter;
import com.czh.demo_mvp.model.LoginModel;
import com.czh.demo_mvp.model.OnMyLoginListenr;
import com.czh.demo_mvp.model.imple.LoginModelImp;
import com.czh.demo_mvp.view.LoginView;
/**
* 通过V层与界面交互数据-将从V层获取的数据传给M层-触发观察者模式
* Created by Administrator on 2016/6/8.
*/
public class LoginPresenter implements OnMyLoginListenr {
private LoginView loginView;// V
private LoginModel loginModel;
public LoginPresenter(LoginView loginView) {
this.loginView = loginView;
loginModel = new LoginModelImp();
}
public void login() {
String name = loginView.getName();
String pass = loginView.getPass();
loginModel.login(name, pass, this);//触发登录操作
}
// 观察者模式接收反馈的结果 并通过V层与用户进行沟通
@Override
public void onSuccessLogin() {
loginView.toIndex();
loginView.showToast("登录成功");
}
@Override
public void onFailedLogin() {
loginView.showToast("登录失败");
}
}
M层观察者
/**
* 登录监听
* Created by Administrator on 2016/6/8.
*/
public interface OnMyLoginListenr {
void onSuccessLogin();
void onFailedLogin();
}
M层数据处理的逻辑(在以前的MVC模式中我都是放在C层处理..)
/**
* 登录接口 内含方法
* Created by Administrator on 2016/6/8.
*/
public interface LoginModel {
void login(String name, String pass, OnMyLoginListenr listenr);
}
实现类
package com.czh.demo_mvp.model.imple;
import com.czh.demo_mvp.model.LoginModel;
import com.czh.demo_mvp.model.OnMyLoginListenr;
/**
* 处理逻辑-反馈结果
* Created by Administrator on 2016/6/8.
*/
public class LoginModelImp implements LoginModel {
private String tag = "tag";
@Override
public void login(String name, String pass, OnMyLoginListenr listenr) {
if (name.equals("q") && pass.equals("q")) {
// Log.i(tag, "登录成功");
listenr.onSuccessLogin();// 反馈结果
} else {
// Log.i(tag, "失败");
listenr.onFailedLogin();
}
}
}
15行数据处理结束后,触发了在P层实现的监听器,见LoginPresenter的26行起;
监听器又通过V层的函数 ,对界面进行控制,显示登录结果、提示等。到此,MVP的运行就完成了,附自己画的醒脑流程图...