本文主要是介绍带你一步一步认识MVP -step1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近换了一家公司项目用的架构是MVP之前一直在用MVVM,也用过一段时间MVP,在这里我还是分享下我对mvp的认识,希望这篇博客能帮助到想用mvp的小伙伴们。
为了让大家了解MVP的演变过程我这里先从最简单的来。
1.最简单的MVP
为了节约大家学习成本我这里就将复杂逻辑简单化处理了
首先使我们的model层的处理(这个过程可以使网络请求也可以是数据库查询处理)
public class UserInfoModel {public List<UserInfo> getUserInfo() {List<UserInfo> userInfos = new ArrayList<>();userInfos.add(new UserInfo("a", "1"));userInfos.add(new UserInfo("b", "2"));userInfos.add(new UserInfo("c", "3"));return userInfos;}
}
然后是我们的view层的处理这里我们采用接口形式记录了数据查询的各个状态
public interface UserInfoView {void onLoading(); // 1.正在加载中void onError(); // 2.获取出错了void onSucceed(List<UserInfo> userInfo); // 3.成功了要显示数据
}
之后要处理我们的presenter层了也就是我们的P层
/*** Created by PC-304 on 2018/5/8.* 最简单的MVP*/
public class UserInfoPresenter {private UserInfoModel model;private UserInfoView view;public UserInfoPresenter(UserInfoView view) {this.view = view;model = new UserInfoModel();}public void getDate() {try {List<UserInfo> userInfos = model.getUserInfo();view.onSucceed(userInfos);} catch (Exception e) {view.onError();}}
}
在这里我们的P层的职责主要是
1.调用model层的处理取到数据( List userInfos = model.getUserInfo();)
2.将处理后的结果返回view层的接口(view.onSucceed(userInfos);)
最后是activity层的调用
public class MainActivity extends AppCompatActivity implements UserInfoView {private UserInfoPresenter presenter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);presenter = new UserInfoPresenter(this);presenter.getDate();}@Overridepublic void onLoading() {}@Overridepublic void onError() {//todo 错误提示}@Overridepublic void onSucceed(List<UserInfo> userInfo) {//todo 显示数据列表int count = userInfo.size();}
}
这样的话我们就实现了简单的mvp,mvp最主要的作用即实现了model跟view的隔离,相比较于mvc我们的控制层presenter层不再是将model处理的结果直接塞给我们的view,而是通过接口的回调处理让回调的接口去处理view的操作,在很大程度上减小了activity的负荷同时实现了m层跟v层的隔离,但这样写也是有问题的。
主要问题:在activity结束后如果model层的处理还没结束,当model层的处理结束后再调用view的处理,可能会有空指针异常。
接下来我们就处理这个问题。
首先还是model 层的处理(跟以前一样这里不需要额外处理)
public class UserInfoModel {public List<UserInfo> getUserInfo() {List<UserInfo> userInfos = new ArrayList<>();userInfos.add(new UserInfo("a", "1"));userInfos.add(new UserInfo("b", "2"));userInfos.add(new UserInfo("c", "3"));return userInfos;}
}
view层的处理(也跟以前一样不需要额外处理)
public interface UserInfoView {void onLoading(); // 1.正在加载中void onError(); // 2.获取出错了void onSucceed(List<UserInfo> userInfo); // 3.成功了要显示数据
}
presenter层处理
public class UserInfoPresenter {private UserInfoModel model;private UserInfoView view;public UserInfoPresenter() {model = new UserInfoModel();}public void attach(UserInfoView view) {this.view = view;}public void detach() {this.view = null;}public void getDate() {try {List<UserInfo> userInfos = model.getUserInfo();if (view == null) return;view.onSucceed(userInfos);} catch (Exception e) {view.onError();}}
}
于以前相比
1.多了 attach 和 detach两个方法用于绑定view和解绑view
2.在getDate方法中添加了if (view == null) return;判断有效的防止了空指针
最后是我们的activity层的处理
public class MainActivity extends AppCompatActivity implements UserInfoView {private UserInfoPresenter presenter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);presenter = new UserInfoPresenter();presenter.attach(this);presenter.getDate();}@Overridepublic void onLoading() {}@Overridepublic void onError() {//todo 错误提示}@Overridepublic void onSucceed(List<UserInfo> userInfo) {//todo 显示数据列表int count = userInfo.size();}@Overrideprotected void onDestroy() {super.onDestroy();presenter.detach();}
}
与以前相比在onDestroy方法中我们添加了presenter.detach()方法这样在activity结束的时候能有效的解绑view,同时在prestnter层中我们添加了对view的非空校验这样在activity结束后如果model有耗时的操作还没处理完我们这里在调用过程中不会有空指针异常。
总结一下
好处
1.在activity销毁的时候 detach防治调用报空指针等错误 相比最初的更安全些
问题
1. 很多代码是公用反复的,attach detach 每个 Presenter 都要有
2. Activity -> View 的 attach detach 每个 View 层也要有
3.可能有内存泄漏风向(我们的attach传入的view是this)
由于篇幅的影响为了让大家看起来不那么累我就在下一篇博客中介绍怎么解决这些问题。
带你一步一步认识MVP -step2
这篇关于带你一步一步认识MVP -step1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!