1,MVP架构模式
概念解释
MVP是Model(数据) View(界面) Presenter(表现层)的缩写,它是MVC架构的变种,强调Model和View的最大化解耦和单一职责原则
Model:负责数据的来源和封装,比如网络请求类,数据库操作类以及java bean,如果有必要则提供接口暴露自己处理数据的状态和进度。
View:负责UI相关,如布局UI的初始化,各种listener的设置。在Android中,我们通常写的Activity和Fragment就是属于View层;在web开发中,html则是View层。
Controller:业务逻辑控制器,主要负责当获取到数据后对数据进行逻辑处理,然后将数据绑定到View上;比如:请求一个url,从网络获取到数据,进行解析javabean,然后各种set数据。对于控制器的概念大家很好理解,因为我们每天都在这样做,在Activity中请求数据然后更新UI。但是结合View的概念来看,很显然Activity和Fragment不但承担了View的任务,还负责完成的Controller的功能,随着业务功能的增多,Activity的代码越来越难以阅读和维护,这就是在Android中使用MVC的弊端,为了解决MVC模式下View层的臃肿,MVP模式应运而生。
Presenter:专门从C独立出来的业务逻辑层,主要负责处理原先View层的业务逻辑,解决了Activity的臃肿问题,让Activity只负责处理UI,职责更加明确;并且将View层的业务逻辑抽取到P层之后,View层与Model层也实现了解耦;便于后期代码的扩展和维护,并且业务逻辑层独立后代码还得到很大的重用性
总结:MVC模式下,V和C纠缠不清,并且View和Model相互关联,而
MVP模式下Model和VIew解耦,便于单元测试,项目维护,代码重用,优点:解耦性强,缺点多了很多接口类
MVVM(了解):叫布局文件和javabean 关联,当修改布局文件时同时会修改 javabean 中的内容。 android端十分麻烦。
android.id = "{user.name}"
2, MAC模式创建登录界面
【1】创建布局
【2】Activity 实现登录,并且对登录页面进行登录模拟
模拟请求网络
public class HttpHelper {
private static HttpHelper mInstance = new HttpHelper();
private HttpHelper() {
}
public static HttpHelper create(){
return mInstance;
}
public void execGet(String url, HttpCallback callback) {
//真正的请求网络操作
}
public void execPost(String url, HttpCallback callback) {
}
public interface HttpCallback {
void onSuccess(String data);
void onFail(Exception e);
}
}
登录页面处理
public class MainActivity extends AppCompatActivity {
@BindView(R.id.et_user)
EditText etUser;
@BindView(R.id.et_psw)
EditText etPsw;
@BindView(R.id.btn_login)
Button btnLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
//点击进行登录
@OnClick(R.id.btn_login)
public void onViewClicked() {
//1,获取用户和密码
String user = etUser.getText().toString();
String psw = etPsw.getText().toString();
if (checkInput(user, psw)) {
HttpHelper.create().execGet("url", new HttpHelper.HttpCallback() {
@Override
public void onSuccess(String data) {
saveUserData();
gotoMain();
}
@Override
public void onFail(Exception e) {
}
});
}
}
/**
* 跳转页面
*/
private void gotoMain() {
//跳转页面
}
/**
* 保存登录信息
*/
private void saveUserData() {
//保存登录信息
}
/**
* 对用户名密码进行操作
* @param user
* @param psw
* @return
*/
private boolean checkInput(String user, String psw) {
//1,判断是否为空
if (TextUtils.isEmpty(user) || TextUtils.isEmpty(psw)) {
showNotNull();
return false;
}
//2,判断长度是否正确
if (user.length() != 11) {
showLengthError();
return false;
}
return true;
}
/**
* 显示登录失败
*/
public void showLoginFail() {
Toast.makeText(this, "登录失败,请检查网络", Toast.LENGTH_SHORT).show();
}
/**
* 显示用户名长度不正确
*/
public void showLengthError() {
Toast.makeText(this, "用户名长度不正确!", Toast.LENGTH_SHORT).show();
}
/**
* 显示用户名和密码不能为空
*/
public void showNotNull() {
Toast.makeText(this, "用户名或密码不能为空!", Toast.LENGTH_SHORT).show();
}
}
3,MVP模式创建登录界面
【1】项目分包
view activity fragment
model bean helper
presenter
【2】BasePresenter 处理Activity的生命周期
创建BasePresenter 里面为对应的Activity提供调用方法
public class BasePresenter {
public void onViewResume(){
}
public void onViewPause(){
}
public void onViewStart(){
//重新开始轮询
}
public void onViewStop(){
//做一些停止ViewPgaer轮询的操作
}
/**
* 当View层被销毁的时候做一些释放操作
*/
public void onViewDestory(){
//比如取消网络请求
}
}
BaseActivity中当生命周期被执行时,调用BasePresenter中对应要实现的方法
public class BaseActivity extends AppCompatActivity {
BasePresenter presenter;
@Override
protected void onResume() {
super.onResume();
presenter.onViewResume();
}
@Override
protected void onPause() {
super.onPause();
presenter.onViewPause();
}
@Override
protected void onStart() {
super.onStart();
presenter.onViewStart();
}
@Override
protected void onStop() {
super.onStop();
presenter.onViewStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消网络请求
presenter.onViewDestory();
}
}
【3】创建登录界面的业务层。
LoginPresenter指定的view层的接口需求,
public interface ILoginView {
void showLoginFail();
void showNotNull();
void showLengthError();
}
登录逻辑的封装抽取类
public class LoginPresenter extends BasePresenter{
private ILoginView loginView;
public LoginPresenter(ILoginView loginView){
this.loginView = loginView;
}
/**
* 登录的方法
* @param user
* @param psw
*/
public void login(String user,String psw){
//2.检查输入是否合法
if(checkInput(user,psw)){
//3.执行登录请求
HttpHelper.create().execPost("url", new HttpHelper.HttpCallback() {
@Override
public void onSuccess(String data) {
//保存登录数据
saveUserData();
//跳转界面
gotoMain();
}
@Override
public void onFail(Exception e) {
loginView.showLoginFail();
}
});
}
}
//跳转主界面
private void gotoMain() {
}
//保存用户登录数据
private void saveUserData() {
}
//检查输入的
private boolean checkInput(String user, String psw) {
//1.判断是否为空
if(TextUtils.isEmpty(user) || TextUtils.isEmpty(psw)){
loginView.showNotNull();
return false;
}
//2.判断长度是否正确
if(user.length()!=11){
loginView.showLengthError();
return false;
}
return true;
}
}
【4】LoginActivity 实现ILoginView 接口 重写对应的UI显示状态。
public class LoginActivity extends BaseActivity implements ILoginView{
@Bind(R.id.et_user)
EditText etUser;
@Bind(R.id.et_psw)
EditText etPsw;
@Bind(R.id.btn_login)
Button btnLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
presenter = new LoginPresenter(this);
}
@OnClick(R.id.btn_login)
public void onClick() {
//1.获取用户和密码
String user = etUser.getText().toString();
String psw = etPsw.getText().toString();
//2.调用loginPresenter进行登录
((LoginPresenter)presenter).login(user,psw);
}
//显示登录失败
public void showLoginFail() {
Toast.makeText(this, "登录失败,请检查网络", Toast.LENGTH_SHORT).show();
}
//显示用户名长度不正确
public void showLengthError() {
Toast.makeText(this, "用户名长度不正确!", Toast.LENGTH_SHORT).show();
}
//显示用户名和密码不能为空
public void showNotNull() {
Toast.makeText(this, "用户名或密码不能为空!", Toast.LENGTH_SHORT).show();
}
}