Android MVP架构的使用

时间:2021-01-30 21:12:00

前言

在现实项目中,我们经常会遇到这样一种情况,就是一个Activity类不仅要处理几种业务逻辑,同时还要兼顾着数据的请求以及UI的操作,这样造成的后果就是整个类的代码会出现上千行,更有胜者是几千行。显而易见,这种处理方式是不妥的,不仅违反了面向对象中单一职责原则,而且对于整个项目来说,也不利于项目的扩展和维护。(单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。)那么,面对这种情况,我们该如何去架构整个项目?由于android项目本身就是MVC架构的体现,Activity充当了Controller,所以我们需要一种新的架构去替代MVC。

MVP初步了解

MVP:(Model-View-Presenter)它是从MVC模式演变而来的,它与MVC模式相同的地方是,Controller/Presenter负责逻辑的处理,Model提供数据,View负责展示。作为一种新的模式,MVP与MVC有着一个重大的区别,在MVP中View并不直接使用Model,它们之间的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从Model中读取数据而不是通过Controller。

MVC图示

Android MVP架构的使用

MVP图示

Android MVP架构的使用

使用MVP的优点:

  • 模型与视图完全分离,我们可以修改视图而不影响模型
  • 可以更高效的使用模型,因为所有的交互都发生在一个地方,即Presendter内部
  • 我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常有用,因为视图的变化总是比模型的变化频繁。
  • 如果我们把逻辑放在Presenter中,那么我们就可以脱离用户来测试这些逻辑(单元测试)

MVP在Android中使用

  • View层负责处理用户时间和视图部分的展示,在Android中,它可能是Activity或者Fragment类
  • Model层负责访问数据。数据可以是远程Server API,本地数据库或者Share的Preference等
  • Presenter层是链接(或适配)View和Model的桥梁

示例

项目结构
Android MVP架构的使用

定义一接口INewsView,作为View层和Presenter层关联的纽带,View层去实现该接口,而Presenter通过INewsView进行改变Activity的UI,同时Presenter类也和Model层进行关联操作
INewsView接口

public interface INewsView {
void initView();//初始化控件

void startLoad();//开始请求数据

void loadSuccess(List<NewsBean> newsBeanList);//请求成功,数据不为空

void loadFail();//请求失败

void loadEmpty();//请求成功,数据为空

}

Activity类去实现该接口,进行UI逻辑操作

public class MainActivity extends AppCompatActivity implements INewsView{

private NewsPersenter newsPersenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
newsPersenter = new NewsPersenter(this);
newsPersenter.requestData();
}

@Override
public void initView() {
//初始化控件
}

@Override
public void startLoad() {
//请求数据前UI操作
}

@Override
public void loadSuccess(List<NewsBean> newsBeanList) {
//请求成功,数据不为空,UI操作
}

@Override
public void loadFail() {
//请求失败,UI操作
}

@Override
public void loadEmpty() {
//请求成功,数据为空,UI操作
}
}

NewsPresenter类

public class NewsPersenter {
private INewsView iNewsView;

public NewsPersenter(INewsView iNewsView) {
this.iNewsView = iNewsView;
this.iNewsView.initView();
}

public void requestData() {
//请求数据前数据前UI操作
iNewsView.startLoad();
//请求数据,异步请求
NewsHttpRequest.requestNewsList(new Callback<List<NewsBean>>() {
@Override
public void onResponse(Response<List<NewsBean>> response) {
if (response == null || response.body() == null || response.body().isEmpty()) {
//请求成功,无数据
iNewsView.loadEmpty();
} else {
//请求成功,有数据
iNewsView.loadSuccess(response.body());
}
}

@Override
public void onFailure(Throwable t) {
//请求失败
iNewsView.loadFail();
}
});
}
}

NewsHttpRequest类,进行数据请求,Model层操作

public class NewsHttpRequest {

public static interface INewsRequest {
@GET("/NewsService/newsList")
Call<List<NewsBean>> getNewsBeanList();
}

public static void requestNewsList(Callback<List<NewsBean>> callBack) {
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://localhost:8080")
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofit.create(INewsRequest.class).getNewsBeanList().enqueue(callBack);
}
}

ps:当项目比较小,业务逻辑不多的时候,不建议使用MVP模式