一、何为MVP
说起MVP模式,必须先从MVC这种传统的设计模式说起,一般传统的app页面布局的设置逻辑和业务处理了逻辑都写在activity层中,这样随着项目的迭代,老的代码将也来越乱,每次需求更改,业务数据层的逻辑更改和界面层的逻辑更改都将在activity中修改,如果是自己写的还好,若是上个哥们的项目,而且还写的很乱的,那么你懂得。
先盗一张图,因为我们要用这张图来解释。
先盗一张图,因为我们要用这张图来解释。
MVC模式中View层和Model层都跟controller层关联,每次业务逻辑的更改都基本要在同一个类中修改,众所周知,写代码不难,改代码那是灾难啊,特别还不是自己的写的代码,这个时候那种感觉你懂得。如果采用MVP的话,将业务逻辑Model层和视图层分开,那么该需求的时候我们操作就好做点。比如改页面的页面变化修改view层代码,model层变化在model层改,这样更清晰。理论离不开实战,接下来用代码层讲解吧。
二、工程
工程结构如下:
1、model层处理:
定义一个接口规范:IGirlModel
public interface IGirlModel {
void loadGirl(GrilOnLoadListener listener);
interface GrilOnLoadListener{
void onComplete(List<Girl> girls);
}
}
接着是其实现类,负责填充数据:
public class GirlModelImpl implements IGirlModel{
@Override
public void loadGirl(GrilOnLoadListener listener) {
//加载数据
List<Girl> data = new ArrayList<>();
data.add(new Girl("刘亦菲","https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=a38cb7e5af1ea8d39e2f7c56f6635b2b/c2fdfc039245d6884449b2faadc27d1ed21b2420.jpg"));
data.add(new Girl("杨幂","https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=4cd858ed9f0a304e462fa8a8b0a1cce3/d53f8794a4c27d1e63dc172d13d5ad6edcc43864.jpg"));
data.add(new Girl("唐嫣","https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike180%2C5%2C5%2C180%2C60/sign=ac5b0fe02d381f308a1485fbc868276d/08f790529822720e3e87df227ecb0a46f31fab98.jpg"));
data.add(new Girl("景甜","https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike180%2C5%2C5%2C180%2C60/sign=c9b60227d52a6059461de948495d5ffe/30adcbef76094b363416f503a1cc7cd98c109d5c.jpg"));
data.add(new Girl("赵丽颖","https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike150%2C5%2C5%2C150%2C50/sign=826890e23a01213fdb3e468e358e5db4/48540923dd54564e9d204002b0de9c82d1584f47.jpg"));
data.add(new Girl("Angelababy","https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=005e5fcd9aef76c6c4dff379fc7f969f/9358d109b3de9c8234db74636681800a18d843a4.jpg"));
data.add(new Girl("孙俪","https://gss3.bdstatic.com/-Po3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=e82ca234a18b87d6444fa34d6661435d/203fb80e7bec54e76de10a1bb9389b504fc26aa1.jpg"));
//返回数据
listener.onComplete(data);
}
}
2、View层处理
该类主要定义一些页面操作,由activity去实现完成
/**
* 视图层接口
*/
public interface IGrilView {
/**
* 加载提示
*/
void showLoading();
/**
* 显示数据
* @param data
*/
void showGirls(List<Girl> girls);
}
3、presenter层
主要负责链接俩层将逻辑串起来
public class GirlPresenter {
//View引用
IGrilView mGirlView;
//Model引用
IGirlModel girlModel = new GirlModelImpl();
public GirlPresenter(IGrilView mGirlView) {
this.mGirlView = mGirlView;
}
//
public void fetch(){
//显示进度条
if (girlModel != null) {
//显示进度条
if (mGirlView != null) {
mGirlView.showLoading();
}
girlModel.loadGirl(new IGirlModel.GrilOnLoadListener() {
@Override
public void onComplete(List<Girl> girls) {
//返回数据
//显示到view层
mGirlView.showGirls(girls);
}
});
}
//加载数据
}
}
4、activity中调用
public class MainActivity extends AppCompatActivity implements IGrilView {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.lv);
new GirlPresenter(this).fetch();
}
@Override
public void showLoading() {
Toast.makeText(this, "正在加载中...", Toast.LENGTH_SHORT).show();
}
@Override
public void showGirls(List<Girl> girls) {
listView.setAdapter(new GirlAdapter(this,girls));
}
}
5、优化
此时项目效果已将出来了,但是这种情况是存在问题的,问题就出在presenter层,该层持有view层的引用,而view层接口的实现都是activity,那么这时候就有内存泄漏了。怎么解决呢,其实简单的解决就是让view层的引用是弱引用,这样gc会在内存不足的时候将这个对象回收掉,这样就避免了内存泄漏,代码如下:
public class GirlPresenter {
//View引用
// IGrilView mGirlView;
WeakReference<IGrilView> mGirlView;
//Model引用
IGirlModel girlModel = new GirlModelImpl();
public GirlPresenter(IGrilView mGirlView) {
this.mGirlView = new WeakReference<IGrilView>(mGirlView);
}
//
public void fetch(){
//显示进度条
if (girlModel != null) {
//显示进度条
if (mGirlView != null) {
mGirlView.get().showLoading();
}
girlModel.loadGirl(new IGirlModel.GrilOnLoadListener() {
@Override
public void onComplete(List<Girl> girls) {
//返回数据
//显示到view层
mGirlView.get().showGirls(girls);
}
});
}
//加载数据
}
}