MVP 模式将Activity 中的业务逻辑全部分离出来,让Activity 只做 UI 逻辑的处理,所有跟Android API无关的业务逻辑由 Presenter 层来完成。
Model 层中包含着具体的数据请求,数据源。
Activity 和Fragment 视为View层,负责处理 UI。
Presenter 为业务处理层,既能调用UI逻辑,又能请求数据。
首先是Model层,Model层用来获得数据比如说http请求得到的数据,首先定义model层的接口,在BaseModel里添加了两个接口。
public interface BaseModel {
//这里写http请求的接口
void login(String username, String password, onFinishedListener listener);
void exit( onFinishedListener listener);
}
在BaseModelImpl来实现接口里的方法,用来获得数据这里我模拟了耗时操作来获取数据并回调接口onFInishListener
public class BaseModelImpl implements BaseModel {
//这里写http请求
@Override
public void login(final String username,final String password,final onFinishedListener listener) {
new Handler().postDelayed(new Runnable() {
@Override public void run() {
boolean error = false;
if (TextUtils.isEmpty(username)){
listener.onError("用户名不存在");//model层里面回调listener
error = true;
return;
}
if (TextUtils.isEmpty(password)){
listener.onPasswordError();
error = true;
return;
}
if (!error){
// 返回方法名和http请求的结果
listener.onSuccess("login","{}");
}
}
}, 2000);
}
@Override
public void exit(final onFinishedListener listener) {
new Handler().postDelayed(new Runnable() {
@Override public void run() {
// 返回方法名和http请求的结果
listener.onSuccess("exit","{}");
}
}, 2000);
}
}
接口onFInishListener是获得数据完成时根据返回结果进行不同的处理
public interface onFinishedListener {
//通用错误提示
void onError(String error);
//需要特殊处理的错误提示
void onUsernameError();
void onPasswordError();
/**
*
* @param way 方法名
* @param result 返回结果
*/
void onSuccess(String way,String result);
}
BaseView是改变UI层的接口,在Activity或者Fragment调用改变UI,BaseView的实现在activity或者fragment实现
public interface BaseView {
void showProgress();
void hideProgress();
void setUsernameError();
void setPasswordError();
void setError(String error);
void success(String way, String result);
}
BasePresentesenter的作用连接Model 层和View
public interface BasePresenter {
void login(String username, String password);
void exit();
void onDestroy();
}
下面是实现 BasePresentesenter的方法
public class BasePresenterImpl implements BasePresenter, onFinishedListener {
private BaseView baseView;
private BaseModel baseModel;
public BasePresenterImpl(BaseView baseView){
this.baseView = baseView;
this.baseModel = new BaseModelImpl();
}
@Override
public void login(String username, String password) {
if (baseView != null) {
baseView.showProgress();
}
baseModel.login(username, password, this);
}
@Override
public void exit() {
if (baseView != null) {
baseView.showProgress();
}
baseModel.exit(this);
}
@Override
public void onDestroy() {
baseView = null;
}
@Override
public void onError(String error) {
if (baseView != null) {
baseView.setError(error);
baseView.hideProgress();
}
}
@Override
public void onUsernameError() {
if (baseView != null) {
baseView.setUsernameError();
baseView.hideProgress();
}
}
@Override
public void onPasswordError() {
if (baseView != null) {
baseView.setPasswordError();
baseView.hideProgress();
}
}
@Override
public void onSuccess(String way, String result) {
if (baseView != null) {
baseView.success(way,result);
baseView.hideProgress();
}
}
}
UI层实现BaseView的接口下面是实例
public class MainActivity extends AppCompatActivity implements BaseView,View.OnClickListener {
private ProgressBar progress;
private BasePresenter presenter;
private Button button;
private EditText username;
private EditText password;
private Button exit;
private CustomDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog = new CustomDialog(this, R.style.CustomDialog);
progress = (ProgressBar)findViewById(R.id.progress);
presenter = new BasePresenterImpl(this);
username = (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(this);
exit = (Button)findViewById(R.id.exit);
exit.setOnClickListener(this);
}
@Override
public void showProgress() {
progressDialog.show();
}
@Override
public void hideProgress() {
progressDialog.cancel();
}
@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 setError(String error) {
Toast.makeText(this,error,Toast.LENGTH_SHORT).show();
}
@Override
public void success(String way, String result) {
Toast.makeText(this,way,Toast.LENGTH_SHORT).show();
//根据调用的接口,更新成功的ui
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:
presenter.login(username.getText().toString(), password.getText().toString());
break;
case R.id.exit:
presenter.exit();
break;
}
}
@Override
protected void onDestroy() {
presenter.onDestroy();
super.onDestroy();
}
}
在baseView定义不同的错误,在Activity中处理他们来改变ui,比如说用户名错误我们就调用setUsernameError的方法来提示用户用户名错误,如果调用成功时会回调success方法,第一个参数是调用方法的名称,用来区分各个接口调用成功之后的不同处理,第二个参数result是返回的数据,用来处理或者填充列表。
github的网址:https://github.com/tempest1/androidMvp