mvp
在mvc中 control 指的是 activity
在 mvp 中 Activity 仅仅表示的是View层而已 Activity 已变得简单了 所有逻辑交给 P层或者M层去实现
在mvp中 业务逻辑在P层或者在M层没有绝对的标准,在谷歌的官方文档demo中,业务是在P层实现,但是我们在实际开发中,常常放在M层实现
View 与 Model 层 完全分离
如果需要解耦 View 层 与 Presenter层
代码演示
和上一篇文章的需求一样,点击按钮从网络加载图片,我们采用Mvp架构思想
layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="getImage"
android:text="获取图片" />
<ImageView
android:id="@+id/image"
android:layout_width="100dp"
android:layout_height="100dp" />
</LinearLayout>
javaBean
public class ImageBean
{
// 网络图片请求地址
private String requestPath;
// 结果返回bitmap对象
private Bitmap bitmap;
public String getRequestPath()
{
return requestPath;
}
public void setRequestPath(String requestPath)
{
this.requestPath = requestPath;
}
public Bitmap getBitmap()
{
return bitmap;
}
public void setBitmap(Bitmap bitmap)
{
this.bitmap = bitmap;
}
}
**DownloaderContract 定义接口标准 **
// View层交互,Model层交互共同的需求(契约、合同)
public interface DownloaderContract {
interface M {
// P层告诉M层,需要做什么事情
void requestDownloader(ImageBean imageBean) throws Exception;
}
interface PV {
// V层告诉P层,需要做什么事情
void requestDownloader(ImageBean imageBean);
// P层得到M层的结果返回,再通知V层
void responseDownloaderResult(boolean isSuccess, ImageBean imageBean);
}
}
DownLoaderEngine 真正的Model层 执行下载任务
public class DownLoaderEngine implements DownloaderContract.M {
private DownLoaderPresenter presenter;
public DownLoaderEngine(DownLoaderPresenter presenter) {
this.presenter = presenter;
}
@Override
public void requestDownloader(ImageBean imageBean) throws Exception {
// P层让我做这个需求
new Thread(new DownLoader(imageBean)).start();
}
final class DownLoader implements Runnable {
private final ImageBean imageBean;
public DownLoader(ImageBean imageBean) {
this.imageBean = imageBean;
}
@Override
public void run() {
try {
URL url = new URL(imageBean.getRequestPath());
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setRequestMethod("GET");
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = httpURLConnection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
showUi(Constant.SUCCESS, bitmap);
} else {
showUi(Constant.ERROR, null);
}
} catch (Exception e) {
e.printStackTrace();
showUi(Constant.ERROR, null);
}
}
private void showUi(int resultCode, Bitmap bitmap) {
imageBean.setBitmap(bitmap);
presenter.responseDownloaderResult(resultCode == Constant.SUCCESS, imageBean);
}
}
}
P层 view 与 Model 层的中间层 负责接收 view层的指令 然后告诉 M层 ,当M层完成任务后,再告诉P层,P层再告诉V层
// P层几乎不做事情?谷歌的sample中,P层是包揽了所有的活
public class DownLoaderPresenter implements DownloaderContract.PV {
private MainActivity view;
private DownLoaderEngine model; // 下载的模型
public DownLoaderPresenter(MainActivity view) {
this.view = view;
model = new DownLoaderEngine(this);
}
@Override
public void requestDownloader(ImageBean imageBean) {
// 接收到View层的指令,去完成某个需求(可以自己完成,也可以让别人去完成)
try {
model.requestDownloader(imageBean);
} catch (Exception e) {
e.printStackTrace();
// 省略了异常的处理
}
}
@Override
public void responseDownloaderResult(final boolean isSuccess, final ImageBean imageBean) {
// 将完成的结果告知View层(刷新UI)
view.runOnUiThread(new Runnable() {
@Override
public void run() {
view.responseDownloaderResult(isSuccess, imageBean);
}
});
}
}
MainActivity 我们的V层
public class MainActivity extends AppCompatActivity implements DownloaderContract.PV
{
private ImageView imageView;
private DownLoaderPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.image);
presenter = new DownLoaderPresenter(this);
new Thread(new Runnable()
{
@Override
public void run()
{
SystemClock.sleep(50000);
}
}).start();
}
public void getImage(View view)
{
ImageBean imageBean = new ImageBean();
imageBean.setRequestPath(Constant.IMAGE_PATH);
requestDownloader(imageBean);
}
@Override
public void requestDownloader(ImageBean imageBean)
{
if (presenter != null) presenter.requestDownloader(imageBean);
}
@Override
public void responseDownloaderResult(boolean isSuccess, ImageBean imageBean)
{
Toast.makeText(this, isSuccess ? "下载成功" : "下载失败", Toast.LENGTH_SHORT).show();
if (isSuccess && imageBean.getBitmap() != null)
{
imageView.setImageBitmap(imageBean.getBitmap());
}
}
}
以上就是mvp模式的所有代码了,P层几乎什么事也没干,那么这种写法会存在内存泄漏吗?
我们把P层改一改
// P层几乎不做事情?谷歌的sample中,P层是包揽了所有的活
public class DownLoaderPresenter implements DownloaderContract.PV {
private MainActivity view;
private DownLoaderEngine model; // 下载的模型
public DownLoaderPresenter(MainActivity view) {
this.view = view;
model = new DownLoaderEngine(this);
}
@Override
public void requestDownloader(ImageBean imageBean) {
// 接收到View层的指令,去完成某个需求(可以自己完成,也可以让别人去完成)
/* try {
model.requestDownloader(imageBean);
} catch (Exception e) {
e.printStackTrace();
// 省略了异常的处理
}*/
new Thread(new Runnable()//===========================改
{
@Override
public void run()
{
SystemClock.sleep(50000);
}
}).start();
}
@Override
public void responseDownloaderResult(final boolean isSuccess, final ImageBean imageBean) {
// 将完成的结果告知View层(刷新UI)
view.runOnUiThread(new Runnable() {
@Override
public void run() {
view.responseDownloaderResult(isSuccess, imageBean);
}
});
}
}
可以看到 在P层 执行 SystemClock.sleep(50000); 也会引发内存的泄漏,为什么了? 因为 p层持有 MainActivity 也就是 V层 的引用,当我们点击back健退出到桌面后,P层中的这个线程还在执行,而我们的MainActivity 已经退出了 ,但是由于P持有MainActivity 引用,导致 MainActivity 不能被gc,导致内存泄漏