您的位置:首页 > 运维架构 > 网站架构

Android开发之MVP架构详解

2016-12-02 23:42 417 查看
Android开发之MVP架构详解
一、MVP和MVC的一点感悟

  MVP模式估计每个人都了解一点,是从MVC演变而来,随着项目的逐渐变大考虑到产品的维护以及扩展性,MVC的短处逐渐暴露出来,从而让耦合性更低的MVP就得到了人们的青睐。

  对于两则的优缺点以及特性介绍网上有一大堆的博客,此处我也不想再去重复,只是简单记录一下自己的感觉和认识。

  我们在用MVC写项目的时候,随着项目的变大,Activity中的东西会越来越多,Model数据的逻辑处理,VIew的显示全部掺杂在一起,后期的维护和扩展非常费劲,如果是接手别人的项目来维护,那更是让人头大。然而,MVP模式开发的项目看上去就显得让人一目了然,对Activity的任务减轻了不少,结构分明,耦合性更低。

  MVP模式中Activity承担了VIew的角色,Model依然是负责数据的处理,而Model和VIew之间交互的责任则由Presenter来完成,充当一个中介的作用,VIew和Model之间不能之间进行通信。

废话不多说,用代码来说明,Demo很简单,是一个ListView列表,就不截图了。

二、Demo介绍

Demo中VIew层和Model层都使用了接口,

下面是目录结构:



实体类News

public class News {

private String name;
private String content;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}




Model 的接口INewsModel

/**
* model 接口
*/

public interface INewsModel {

/**
* 加载数据
*/
void loadGirls(GirlLoadOnListener listener);

/**
* 回调监听,数据接收完成
*/
interface GirlLoadOnListener {
//数据传递过来
void onComplete(List<News> news);
}

}


 Model的接口实现类

/**
* Model接口实现类
*/

public class NewsModelImpl implements INewsModel {
//加载数据
@Override
public void loadloadNews(GirlLoadOnListener listener) {
List<News> dataList = new ArrayList<>();
for (int i = 0; i < 15; i++) {
News g = new News();
//内容随便敲的,不重要
g.setName("案件发is的肌肤" + i);
g.setContent("撒娇佛is戴假发老司机放假啊考虑实际得分i11" + i);
dataList.add(g);
}

listener.onComplete(dataList);
}
}


VIew 的接口INewsView

/**
* VIew层接口
*/

public interface INewsView {

/**
* 显示数据
*/
void showData(List<News> news);

/***
* 显示进度
*/
void showLoading();

/**
* 隐藏进度
*/
void hideLoading();
}


view的接口实现类,其实就是我们的Activity,对于BaseActivity,是为了防止内存溢出使用了泛型,之后介绍。

public class NewsListActivity extends BaseActivity<INewsView, NewsPresenter> implements INewsView {

private ListView listView;
private NewsAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

listView = (ListView) findViewById(R.id.listview);
//view 和 model绑定
mPresenter.fetch();
}

@Override
protected NewsPresenter createPresenter() {
return new NewsPresenter();
}

@Override
public void showData(List<News> news) {
adapter = new NewsAdapter(NewsListActivity.this, news);
listView.setAdapter(adapter);
}

@Override
public void showLoading() {
Toast.makeText(this, "正在加载中...", Toast.LENGTH_SHORT).show();
}

@Override
public void hideLoading() {

}
}




Presenter 层,BasePresenter中对VIew有引用,为了防止内存溢出使用了弱引用,后面详细介绍。

/**
* <p>
* 中间人
* girls view 和 model 的桥梁
*/

public class NewsPresenter extends BasePresenter<INewsView> {

private INewsModel mGirlModel = new NewsModelImpl();

/**
* view 和model bind
*/
public void fetch() {
//显示进度
getView().showLoading();
//获取数据
mGirlModel.loadloadNews(new INewsModel.GirlLoadOnListener() {
@Override
public void onComplete(List<News> girls) {
//显示数据
getView().showData(girls);
//隐藏进度
getView().hideLoading();
}
});
}

}


贴出BaseActivity和 BasePresenter代码

BaseActivity中对Presenter进行了绑定和解除绑定的操作,这是为了避免我们在异步获取网络数据时,用户点击了返回键,此时的Activity就执行了onDestroy方法,但是在Presenter中仍然持有VIew的引用,造成不能及时的回收,从而引起内存溢出。

  所以在onDestroy中进行解绑是很必要的,同时在Presenter中引用的VIew使用弱引用,避免内存溢出。

/**
* BaseActivity
*/
public abstract class BaseActivity<V, T extends BasePresenter<V>> extends AppCompatActivity {

protected T mPresenter;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建presenter
mPresenter = createPresenter();
//绑定VIew
mPresenter.attachView((V) this);
}

@Override
protected void onDestroy() {
super.onDestroy();
//解除绑定
mPresenter.detachView();
}

//创建Presenter
protected abstract T createPresenter();
}


BasePresenter中对传入的VIew进行了弱引用,VIew一般是我们使用的Activity或Fragment,如果直接进行引用容易造成内存溢出。

/**
* BasePresenter
*/
public class BasePresenter<T> {

/**
* View的弱引用
*/
protected WeakReference<T> mViewRef;

/**
* 关联
*/
public void attachView(T view) {
mViewRef = new WeakReference<T>(view);
}

/**
* 解除关联
*/
public void detachView() {
if (mViewRef != null) {
mViewRef.clear();
}
}

/**
* 得到VIew
* @return
*/
protected T getView() {
return mViewRef.get();
}

}


demo运行结果就是一个简单的ListVIew。本人菜鸟,欢迎评论指导。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: