MVP在Android中的初学之路
最近开始学习Android的架构模式,了解到从之前众所周知的MVC到MVP 甚至现在流行的MVVM等架构。想着以前都是使用MVC来开发,本想直接上MVVM的不过想着一步步来先了解MVP架构,这样才能更加清楚各种架构的优劣之分。才能再以后工作中结合业务选取合适的架构。开发起来也会更加省事省心。当然架构这种东西也只是相对你的项目来选可能MVP更好 也可能MVVM更好而已。
先介绍下:
MVP的三个模块:Model、View、Presenter
View:负责视图部分展示、视图事件处理。Activity、Fragment、Dialog、ViewGroup等 呈现视图的组件都可以承担该角色。
Model:负责数据的请求、解析、过滤等数据层操作。
Presenter: View和Model交互的桥梁。
镇楼图(Copy):
优点:
1.降低耦合度,隐藏数据,使Activity(或Fragment)中代码更加简洁,只负责处理View的职责;
2.模块职责分工明确;
3.方便单元测试开发;
4.代码复用性较高。
案例分析:
UI层的接口:
View
public interface IGrilView {
/**
* UI业务逻辑 加载进度条
*/
void showLoading();
void showGrils(List<Girl> grils);
}
Mode:
/**
* 模型层
*/
public class GirlModeImlV implements IGirlMode {
@Override
public void loaddata(GirlOnLoadlitener girlOnLoadlitener) {
final List<Girl> data = new ArrayList<Girl>();
data.add(new Girl(R.drawable.f1, "五颗星", "佰仟媚儿初夏新款韩版时尚潮流女个性 字母印花无袖露脐上衣"));
data.add(new Girl(R.drawable.f2, "四颗星", "迷依诗诺夏天新款韩版女装性感夜店欧美风字母印花牛仔露脐背心上衣"));
data.add(new Girl(R.drawable.f3, "五颗星", "迷依诗诺春夏欧美新款性感女装单排扣牛仔背心露脐上衣"));
data.add(new Girl(R.drawable.f4, "三颗星", "美莉丹 新款欧美单排扣牛仔背心露脐上衣"));
data.add(new Girl(R.drawable.f5, "五颗星", "夏季新款韩版时尚个性字母无袖露脐上衣"));
data.add(new Girl(R.drawable.f6, "三颗星", "新款欧美单排扣牛仔背心露脐上衣"));
data.add(new Girl(R.drawable.f7, "四颗星", "夏装新款下摆波浪边挂脖露肩"));
data.add(new Girl(R.drawable.f8, "五颗星", "夏天新款欧美时尚潮流休闲百"));
data.add(new Girl(R.drawable.f9, "四颗星", "迷依诗诺夏季新款小香风甜美性感夜"));
data.add(new Girl(R.drawable.f10, "三颗星", "安巴克夏季新款韩版时尚套装性感"));
girlOnLoadlitener.complete(data);
}
}
/**
* 监听数据返回
*/
public interface IGirlMode {
void loaddata(GirlOnLoadlitener girlOnLoadlitener);
interface GirlOnLoadlitener {
void complete(List<Girl> list);
}
}
MainActivity:
public class MainActivity extends AppCompatActivity implements IGrilView {
ListView listView;
GirlPresenter girlPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listview);
//实例化P层 并抓取数据
girlPresenter = new GirlPresenter(this);
girlPresenter.fectch();
}
@Override
public void showLoading() {
Toast.makeText(this, "正在加载中...", Toast.LENGTH_SHORT).show();
}
@Override
public void showGrils(List<Girl> grils) {
listView.setAdapter(new GirlListAdapter(this, grils));
}
}
主要的P层:
public class GirlPresenter {
//持有UI层的引用
IGrilView iGrilView;
//数据层的引用
IGirlMode iGirlMode = new GirlModeImlV();
public GirlPresenter(IGrilView iGrilView) {
this.iGrilView = iGrilView;
}
public void fectch() {
iGrilView.showLoading();
if (iGirlMode != null) {
iGirlMode.loaddata(new IGirlMode.GirlOnLoadlitener() {
@Override
public void complete(List<Girl> list) {
//回调视图层
iGrilView.showGrils(list);
}
});
}
}
}
这种应该是比较简单的MVP架构方式了。不过这种存在的问题也不少
1.持有Activity的引用 在网络加载时退出 会造成OOM.
2.P层和V层太复杂 可以进行封装成BasePresenter BaseActivity
下面是改造的:
BasePresenter:采用泛型在Activity的onCreate执行绑定一个弱引用 在onDestory方法进行分离达到解除引用置空 让GC回收掉。
/**
* @param <T> 对应每个Activity的UI Presnter
*/
public abstract class BasePresenter<T> {
/**
* 持有UI接口的弱引用
*/
protected WeakReference<T> mWeakReference;
/**
* 绑定UI对象引用
*/
public void attachView(T view) {
mWeakReference = new WeakReference<T>(view);
}
/**
* 加载数据
*/
public abstract void fectch();
/**
* 解绑UI的引用对象
*/
public void dettach() {
if (mWeakReference != null) {
mWeakReference.clear();
mWeakReference = null;
}
}
}
BaseActivity: 这里也采用泛型和采用模板法 让具体的子类去实现Presenter
public abstract class BaseAcivity<V, T extends BasePresenter<V>> extends AppCompatActivity {
protected T mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = createPresenter();
mPresenter.attachView((V) this);
}
protected abstract T createPresenter();
@Override
protected void onDestroy() {
mPresenter.dettach();
super.onDestroy();
}
}
具体的实现MvpMainActivity
public class MvpMainActivity extends BaseAcivity<IGrilView, MvpGirlPresenter<IGrilView>> implements IGrilView {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listview);
mPresenter.fectch();
}
@Override
protected MvpGirlPresenter<IGrilView> createPresenter() {
return new MvpGirlPresenter<>(this);
}
@Override
public void showLoading() {
Toast.makeText(this, "正在加载中...", Toast.LENGTH_SHORT).show();
}
@Override
public void showGrils(List<Girl> grils) {
listView.setAdapter(new GirlListAdapter(this, grils));
}
}
因为这是一个比较简单的MVP,没有结合RxJava Retrofit Okhttp3等框架 不过后面会尝试写这一部分。以上如有写得不对的请指正。感谢各位的阅读。