刚开始学安卓时也尝试去学习过mvp,但当时对于抽象和设计模式都不太熟悉,看到接口那么多以及实现有点懵,也就没有学习。本文是根据网上一篇博客所作的mvp学习笔记。
在使用传统写法时,会在Activity
中实现数据的传输以及视图的管理,当业务逻辑复杂起来的时候难免会陷入代码冗余的境地,此时Activity
的任务将变得繁重起来。mvp将逻辑实现和视图展示分开,Activity
只负责视图上的更新与展示。
由图可知分为三个部分:
View:在安卓中即
Activity
,负责页面显示Model:负责业务逻辑
Presenter:是View与Model的纽带
以前不知道为什么要定义那么多接口,其实现在想想无非是让这个类具有接口中的行为,具有这些行为也就相当于这个类可以做这些事。将一些行为抽象出来让类看上去功能分明,该做什么不该做什么。
下面以一个下载网上图片然后显示的小功能作为mvp模式例子,效果如下:
注:由于现场切换没做好,看起来进度条不完整
根据需求可以这么设计:
- View的职责:
- 提供网上图片的url地址
- 提供一个点击下载的按钮
- 有一个进度条显示进度
- 提供展示图片的
ImageView
- Model的职责:
- 发起网络请求
- 数据处理
- Presenter的职责:
- 将View的请求委托给Model处理
- 将Model中处理好的数据传给View
设计想好后开撸,下面是项目图。前面说了,接口主要是定义一类行为和功能,让实现的类看上去功能分明。
public interface IDownloadModel {
// 下载
void downloadImage(String url);
}
public interface IDownloadView {
void setProgressBar(int progress);
void onSuccess(Bitmap bitmap);
void onFailed(String result);
}
public interface IDownloadPresenter {
void download(String url);
void doSuccess(Bitmap bitmap);
void doFailed(String result);
void getProgress(int progress);
}
分别创建DownloadModel、DownloadActivity、DownloadPresenter三个类实现对应的接口。
首先看View页面展示与交互的实现:
private void init() {
// 控件初始化
mPresenter = new DownloadPresenter(DownloadActivity.this);
mDownload.setOnClickListener((v) -> {
if (TextUtils.isEmpty(mUrl.getText().toString()))
mPresenter.download("http://img2.myhsw.cn/2015-11-19/e18k6yeb.jpg");
else
mPresenter.download(mUrl.getText().toString());
mProgressBar.setVisibility(View.VISIBLE);
mImage.setImageBitmap(null);
});
}
@Override
public void setProgressBar(int progress) {
// 设置进度
mProgressBar.setProgress(progress);
}
@Override
public void onSuccess(Bitmap bitmap) {
// 下载成功
mProgressBar.setVisibility(View.GONE);
Toast.makeText(this, "download successful", Toast.LENGTH_SHORT).show();
mImage.setImageBitmap(bitmap);
}
@Override
public void onFailed(String result) {
mProgressBar.setVisibility(View.GONE);
Toast.makeText(this, "the url is fault", Toast.LENGTH_SHORT).show();
}
然后是presenter
的枢纽功能:
public DownloadPresenter(IDownloadView view) {
mDownloadView = view;
mDownloadModel = new DownloadModel();
mDownloadModel.setPresenter(this);
}
@Override
public void download(String url) {
mDownloadModel.downloadImage(url);
}
@Override
public void doSuccess(Bitmap bitmap) {
mDownloadView.onSuccess(bitmap);
}
@Override
public void doFailed(String result) {
mDownloadView.onFailed(result);
}
@Override
public void getProgress(int progress) {
mDownloadView.setProgressBar(progress);
}
最后是具体逻辑的实现:
private void netWork() {
new Thread(() -> {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
connection = (HttpURLConnection) new URL(mUrl).openConnection();
connection.setRequestMethod("GET");
if (connection.getResponseCode() != 200) {
doFailed("下载失败惹~~,请检查url是否正确");
return;
}
int total = connection.getContentLength();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len,now = 0;
while ((len = connection.getInputStream().read(buffer)) != -1) {
now += len;
getProgress((int) (now / total));
outputStream.write(buffer, 0, len);
}
byte[] bytes = outputStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
doSuccess(bitmap);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
}
}).start();
}