A、Android之MVC模式
MVC (Model-View-Controller):
M是指逻辑模型,V是指视图模型,C则是控制器。
一个逻辑模型可以对于多种视图模型,比如一批统计数据你可以分别用柱状图、饼图来表示。一种视图模型也可以对于多种逻辑模型。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式,而C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
MVC好处:从用户的角度出发,用户可以根据自己的需求,选择自己合适的浏览数据的方式。比如说,对于一篇在线文档,用户可以选择以HTML网页的方式阅读,也可以选择以pdf的方式阅读。从开发者的角度,MVC把应用程序的逻辑层与界面是完全分开的,最大的好处是:界面设计人员可以直接参与到界面开发,程序员就可以把精力放在逻辑层上。而不是像以前那样,设计人员把所有的材料交给开发人员,由开发人员来实现界面。
在Eclipes工具中开发Android采用了更加简单的方法,设计人员在DroidDraw中设计界面,以XML方式保存,在Eclipes中直接打开就可以看到设计人员设计的界面。
Android中界面部分也采用了当前比较流行的MVC框架,在Android中:
1) 视图层(View):一般采用XML文件进行界面的描述,使用的时候可以非常方便的引入。当然,如何你对Android了解的比较的多了话,就一定可以想到在Android中也可以使用JavaScript+HTML等的方式作为View层,当然这里需要进行Java和JavaScript之间的通信,幸运的是,Android提供了它们之间非常方便的通信实现。
2) 控制层(Controller):Android的控制层的重任通常落在了众多的Acitvity的肩上,这句话也就暗含了不要在Acitivity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3) 模型层(Model):对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。
在Android SDK中的数据绑定,也都是采用了与MVC框架类似的方法来显示数据。在控制层上将数据按照视图模型的要求(也就是Android SDK中的Adapter)封装就可以直接在视图模型上显示了,从而实现了数据绑定。比如显示Cursor中所有数据的ListActivity,其视图层就是一个ListView,将数据封装为ListAdapter,并传递给ListView,数据就在ListView中现实。
B、 什么是MVP
MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。
模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;
视图(View):负责界面数据的展示,与用户进行交互;
主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来
一、效果图
项目结构
二、Model层,javaBean
package cn.hnshangyu.mvp.bean;
/**
* Created by Administrator on 2016/10/19.
*
* Model
*/
public class User {
public String name;
public String pwd;
}
三、登陆监听
package cn.hnshangyu.mvp.interfaceuse;
/**
* Created by Administrator on 2016/10/19.
*/
public interface OnLoginListener {
void loginSucess();
void loginFailed();
}
四、登陆接口
package cn.hnshangyu.mvp.interfaceuse;
/**
* Created by Administrator on 2016/10/19.
*/
public interface LoginInterface {
void login(String name,String pwd,OnLoginListener loginListener);
}
五、实现(模拟)登陆
package cn.hnshangyu.mvp.interfaceuse;
import android.os.SystemClock;
import android.text.TextUtils;
import cn.hnshangyu.mvp.bean.User;
/**
* Created by Administrator on 2016/10/19.
*/
public class UserLogin implements LoginInterface {
@Override
public void login(final String name, final String pwd, final OnLoginListener loginListener) {
//模拟登陆
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(3000);
if (TextUtils.equals("xiaoguo", name) && TextUtils.equals("123456", pwd)) {
User user = new User();
user.name = name;
user.pwd = pwd;
loginListener.loginSucess();
} else {
loginListener.loginFailed();
}
}
}).start();
}
}
六、View层
package cn.hnshangyu.mvp.view;
/**
* Created by Administrator on 2016/10/19.
*
* View
*/
public interface LoginView{
String getUserName();
String getPassword();
void clearUserName();
void clearPassword();
void showLoading();
void hideLoading();
void toMainActivity();
void showFailedError();
}
七、Presenter层
package cn.hnshangyu.mvp.presenter;
import android.os.Handler;
import android.os.Message;
import cn.hnshangyu.mvp.interfaceuse.OnLoginListener;
import cn.hnshangyu.mvp.interfaceuse.UserLogin;
import cn.hnshangyu.mvp.view.LoginView;
/**
* Created by Administrator on 2016/10/19.
* <p>
* Presenter
*/
public class LoginPresenter {
private static final int LOGIN_SUCESS = 88;
private static final int LOGIN_FAILED = 99;
private LoginView mLoginView;
private UserLogin mUserLogin;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case LOGIN_SUCESS:
mLoginView.toMainActivity();
mLoginView.hideLoading();
break;
case LOGIN_FAILED:
mLoginView.showFailedError();
mLoginView.hideLoading();
break;
}
}
};
public LoginPresenter(LoginView loginView) {
this.mLoginView = loginView;
this.mUserLogin = new UserLogin();
}
public void login() {
mLoginView.showLoading();
mUserLogin.login(mLoginView.getUserName(), mLoginView.getPassword(), new OnLoginListener() {
@Override
public void loginSucess() {
handler.sendEmptyMessage(LOGIN_SUCESS);
}
@Override
public void loginFailed() {
handler.sendEmptyMessage(LOGIN_FAILED);
}
});
}
public void clear() {
mLoginView.clearUserName();
mLoginView.clearPassword();
}
}
八、在Activity中
package cn.hnshangyu.mvp;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import butterknife.ButterKnife;
import butterknife.InjectView;
import cn.hnshangyu.mvp.presenter.LoginPresenter;
import cn.hnshangyu.mvp.view.LoginView;
public class LoginActivity extends AppCompatActivity implements LoginView, View.OnClickListener {
@InjectView(R.id.et_name)
EditText etName;
@InjectView(R.id.et_password)
EditText etPassword;
@InjectView(R.id.login)
Button login;
@InjectView(R.id.clear)
Button clear;
@InjectView(R.id.login_progress)
ProgressBar loginProgress;
private LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.inject(this);
initView();
}
private void initView() {
hideLoading();
loginPresenter = new LoginPresenter(this);
login.setOnClickListener(this);
clear.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.login:
loginPresenter.login();
break;
case R.id.clear:
loginPresenter.clear();
break;
}
}
@Override
public String getUserName() {
return etName.getText().toString().trim();
}
@Override
public String getPassword() {
return etPassword.getText().toString().trim();
}
@Override
public void clearUserName() {
etName.setText("");
}
@Override
public void clearPassword() {
etPassword.setText("");
}
@Override
public void showLoading() {
loginProgress.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
loginProgress.setVisibility(View.GONE);
}
@Override
public void toMainActivity() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
@Override
public void showFailedError() {
Toast.makeText(this,"登陆失败",Toast.LENGTH_LONG).show();
}
}