最近在研究MVP的使用,看了几篇介绍的,
综合了Google的MVPdemo介绍。简单的说一下。
https://github.com/zhuyongit/MVPDemo。这篇说的感觉还不错,分析的挺透彻。
//www.greatytc.com/p/14283d8d3a60这个里面有Google的MVP简单的介绍。
一:基本概念
不管是MVC还是MVP , 都是为了将数据,处理逻辑,与界面分离 , 以达到低耦合的效果 。MVP模式,主要是面向接口编程 , 将Model与View都抽象成接口,用一个Presenter来关联View与Model,Presenter做到一个绑定数据控制界面的中间者 。
下面简单的画下UML图帮助理解:
MVC:M(Model)V(View)C(Controller)
MVP:M(Model)V(View)P(Presenter)
MVC:
MVP:P层持有M层和V层的对象,将M与V关联起来 , 在MVP中将Model与View的操作接口化 , 通过接口回调来完成数据的传递 。
传统的MVP不能更直观的看到IView中的方法和Presenter中的方法的关联。我这里多了一个contract包:里面放的是契约接口。更能直接明了的看到View和Presenter之间的方法。具体的模型图:
下面开始敲代码:
①首先先把基类的Contract和BaseActivity定义好。
/**
* Created by pepys on 2017/5/26.
* description:Contract基类
*/
public interface BaseContract {
interface View {
/**
* 显示loading
*/
void showProgress();
/**
* 隐藏loading
*/
void hideProgress();
}
interface Presenter<T> {
/**
* 初始化操作
*/
void onStart();
/**
* 关联View
* @param view
*/
void attachView(@NonNull T view);
/**
* 防止内存泄漏,在presneter销毁时同事销毁view
*/
void onDestroy();
}
}
public abstract class BaseActivity<V,T extends BaseContract.Presenter<V>> extends FragmentActivity {
protected T mPresneter ;
/**
* create presenter
* @return
*/
protected abstract T createPresenter();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*创建Presenter*/
mPresneter = createPresenter();
/*内存泄漏 , 关联View*/
mPresneter.attachView((V) this);
setContentView(getLayoutID());
findViewByID();
}
protected abstract int getLayoutID();
protected abstract void findViewByID();
@Override
protected void onDestroy() {
super.onDestroy();
mPresneter.onDestroy();
}
}
②基类的presenter实现,主要为了管理View。防止内存泄漏.
public abstract class BasePresenterImpl<T> implements BaseContract.Presenter<T> {
protected T mView;
@Override
public void attachView( T view) {
this.mView = view;
}
@Override
public void onDestroy() {
cancelRequest();
mView = null;
}
/**
* 这个计划是在view销毁的时候同时取消请求
*/
public void cancelRequest() {
//// TODO: 2017/5/26
}
}
③编写业务Contract契约接口,定义业务接口,如果逻辑复杂的话,View 里面的接口可能会比较多~
public interface LoginContract {
interface View extends BaseContract.View {
/*得到用户名*/
String getName();
/*得到密码*/
String getPassword();
void loginSuccess();
void loginFailure();
}
interface Presenter extends BaseContract.Presenter {
/*执行请求处理*/
void login();
}
interface Model {
HashMap<String,String> resultMap = new HashMap<>();
void login(String name, String psw, CallbackListener callback);
}
}
④ 继续敲Model实现类。
/**
* Created by pepys on 2017/5/26.
* description: 这里才是真正的数据请求
*/
public class LoginModelImpl implements LoginContract.Model {
@Override
public void login(final String name, String psw, final CallbackListener callback) {
//模拟请求
callback.before();
try {
Thread.sleep(1000*4);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(name.equals("001")){
resultMap.put("status","成功");
callback.onSuccess(resultMap);
}else{
resultMap.put("status","失败");
callback.onFailure(resultMap);
}
callback.after();
}
}
⑤ 编写presenter实现类 , 定一个两个接口的引用,Model在创建类的时候就创建 , 而View则是通过创建Presenter对象进行传递 。
/**
* Created by pepys on 2017/5/26.
* description:Presneter 这是是处理view和model的地方
*/
public class LoginPresneterImpl extends BasePresenterImpl implements LoginContract.Presenter {
/**
* 持有view引用
*/
private LoginContract.View view;
/**
* 持有model引用
*/
private LoginContract.Model model = new LoginModelImpl();
public LoginPresneterImpl(LoginContract.View view) {
this.view = view;
}
@Override
public void login() {
model.login(view.getName(), view.getPassword(), new CallbackListener() {
@Override
public void before() {
view.showProgress();
}
@Override
public void onSuccess(HashMap hashMap) {
view.loginSuccess();
}
@Override
public void onFailure(HashMap hashMap) {
view.loginFailure();
}
@Override
public void after() {
view.hideProgress();
}
});
}
@Override
public void onStart() {
//这里可以放入进界面就请求的
}
}
⑥Activity实现View接口,在presenter中交互。
public class MainActivity extends BaseActivity<LoginContract.View,BaseContract.Presenter<LoginContract.View>> implements LoginContract.View,View.OnClickListener{
private LoginPresneterImpl presneter ;
private EditText logion_name,logion_pwd;
private Button login_submit;
@Override
protected BaseContract.Presenter<LoginContract.View> createPresenter() {
return presneter = new LoginPresneterImpl(MainActivity.this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected int getLayoutID() {
return R.layout.activity_main;
}
@Override
protected void findViewByID() {
logion_name = (EditText) findViewById(R.id.logion_name);
logion_pwd = (EditText) findViewById(R.id.logion_pwd);
login_submit = (Button) findViewById(R.id.login_submit);
login_submit.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.login_submit:
presneter.login();
break;
}
}
@Override
public void showProgress() {
Toast.makeText(this,"请稍等..",Toast.LENGTH_LONG).show();
}
@Override
public void hideProgress() {
}
@Override
public String getName() {
return logion_name.getText().toString();
}
@Override
public String getPassword() {
return logion_pwd.getText().toString();
}
@Override
public void loginSuccess() {
Toast.makeText(this,"成功..",Toast.LENGTH_LONG).show();
}
@Override
public void loginFailure() {
Toast.makeText(this,"失败..",Toast.LENGTH_LONG).show();
}
}
MVP现在在Android中应用越来越广泛了 。虽然项目文件会比较多 , 但是如果管理好接口类,结构清晰,使用起来还是比较方便的。
具体的demo已经放到github上。
https://github.com/PepysZhu/MVPDemo