Android MVP架构
总结一下MVP架构,谈谈自己对MVP的理解。MVP确实可以在一定程度上减少代码耦合,将View和数据业务分离出来,但是为了MVP而MVP反而会让逻辑更加混乱。
Demo:GitHub/quibbler01/HelloMVP
1、MVP概念
MVP是Model-View-Presenter的简称,即模型-视图-表示器。
1.1、来源
最早在2000年就由IBM旗下的子公司Taligent提出来MVP的概念,当时是针对C++和Java的编程模型。属于MVC模式的变种,目的是为了将UI和业务逻辑剥离。
1.2、M-V-P
M:模型(Model),专注于数据的处理。
V:视图(View),专注于处理数据的可视化以及用户交互。
P:逻辑(Presenter),“逻辑”用于交互与数据传输。

1.3、为什么用MVP
最深的体会是自己写过小程序,那时候也不懂MVP。各种代码,业务逻辑全部挤在一个Activity里面,光是一个Activity就有2000多行代码。定义的各种方法、变量都塞到一个Java类中,后面修改和维护起来会越来越难,虽然自己写的代码对“全局”还是有比较深的印象,但是换个人呢?项目开发中如果所有人都往Activity/View中塞代码,那样最终越来越难以迭代和维护!
所以通过MVP架构,可以将代码很好的组织起来,View的专门负责UI显示,逻辑放到Presenter,数据请求处理放到Model中。层次鲜明代码整体逻辑也比较清晰,不管是项目的功能迭代开发,开始维护都会大大降低难度。
第一次接触项目代码,就是自己从View层逐渐摸索到Presenter层,再到数据Mode层,对整体的项目结构有一个宏观的了解,MVP架构的项目上手会比较容易。
2、MVP优缺点
MVP比没有MVP要好,但是也有不足。
2.1、优点
①符合单一职责原则:M-V-P三层各司其职
②结构清晰,利于项目维护。
③Presenter复用非常方便,功能扩展。项目增加新功能的时候都没动Presenter层,只是在Model中进行开发新增了一种数据。
④便于单元测试。还没用到过Android Unit单元测试
2.2、缺点
①最明显的缺点就是interface接口太多,需要定义很多Callback回调接口。增加代码量。
②内存泄漏隐患,Presenter持有View的引用,而且Presenter大多数写成单例,如果没有释放Presenter持有的引用,即有可能导致内存泄漏!
3、Demo
举个例子,以Hello World!为例,如何改造成MVP。实际小项目上千万不要过度MVP,没必要把简单的问题搞复杂!

3.1、View
就是Activity,其中的TextView更新数据。持有Presenter单例,通过这个实例请求。
public class MainActivity extends AppCompatActivity implements IView {
private Presenter mPresenter;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPresenter = Presenter.getInstance();
initView();
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.unSubscribe();
}
private void initView() {
mTextView = findViewById(R.id.text);
mPresenter.subscribe(this);
}
@UiThread
@Override
public void showTextMessage(String message) {
mTextView.setText(message);
}
}IView层接口,给Presenter回调,更新界面使用。
public interface IView {
public void showTextMessage(String message);
}3.2、Presenter
负责处理View层的请求,从Model层获取数据,再更新View层。
public class Presenter {
private static volatile Presenter sPresenter;
private IView mViewCallback;
private IModel mModel;
private Handler mHandler = new Handler(Looper.getMainLooper());
private Presenter() {
mModel = new Model();
}
public static Presenter getInstance() {
if (sPresenter == null) {
synchronized (Presenter.class) {
if (sPresenter == null) {
sPresenter = new Presenter();
}
}
}
return sPresenter;
}
private Timer mTimer = new Timer();
@MainThread
public void subScribeMessage() {
//应该使用线程池
new Thread(new Runnable() {
@Override
public void run() {
getMessageInternal();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
getMessageInternal();
}
}, 0, 1000);
}
}).start();
}
public void unSubscribeMessage() {
mTimer.cancel();
}
@WorkerThread
private void getMessageInternal() {
final String message = mModel.getMessage();
mHandler.post(new Runnable() {
@Override
public void run() {
if (null != mViewCallback) {
mViewCallback.showTextMessage(message);
}
}
});
}
@MainThread
public void subscribe(@NonNull IView viewCallback) {
mViewCallback = viewCallback;
subScribeMessage();
}
@MainThread
public void unSubscribe() {
mViewCallback = null;
unSubscribeMessage();
}
}3.3、Model
模拟从网络等地方获取数据,耗时操作。
public class Model implements IModel {
private Calendar mCalendar;
private SimpleDateFormat dateFormat;
public Model() {
mCalendar = Calendar.getInstance();
dateFormat = (SimpleDateFormat) SimpleDateFormat.getDateTimeInstance();
}
@WorkerThread
@Override
public String getMessage() {
return getMessageFromServer();
}
@WorkerThread
private String getMessageFromServer() {
mCalendar.setTimeInMillis(System.currentTimeMillis());
return "Hello World!\n\n\n" + dateFormat.format(mCalendar.getTime());
}
}IModel回调接口,给Presenter使用
public interface IModel {
public String getMessage();
}4、TheMVP
MVP架构的一个变种。TheMVP使用Activity作为Presenter层来处理代码逻辑,通过让Activity包含一个ViewDelegate对象来间接操作View层对外提供的方法,从而做到完全解耦视图层。
不详细展开,以后再深入学习一下。GitHub:kymjs/TheMVP
参考博客:

