MVP 入门实践 - 分享自@开发者头条

说到MVP肯定要先说下MVC,想必大家对android的MVC都有很深的了解。

View:布局文件,用于界面显示

Model:业务逻辑和实体模型

Controllor:对应于Activity,用于数据和界面的交互显示

由上图可以看出,View与数据的关系错综复杂,即activity不仅要负责数据的加工还要负责对数据的显示工作。一旦业务逻辑复杂,代码的可读性会大大的下降。

MVP设计思想与MVC有很大的不同,它将数据加工和界面交互的工作分开来做,即增加Presenter 负责完成View于Model间的交互。

这样一来,activity的代码量就会打打的下降。

接下来我们用一个简单的Demo来说明下:

下载Demo

下面就获取图片列表并显示在RecyclerView为例进行说明。

图片api使用的是新浪看见列表数据(声明:数据api仅用于学习交流)

api地址:
http://api.slide.news.sina.com.cn/interface/api_album_photo_col.php?app_key=1985696825&photo_col_id=10&tags=cat&tagmode=any&jsoncallback=get_witness_list&format=json&page=1&num=20&_=1458029148787

请求使用GET方式,大家可以根据需要更改里面的参数,如page和num等

该api返回数据的格式为get_witness_list(json),所以不能直接转换为对象,我们只需要去除()内的json数据即可,具体做法不再赘述,下面来具体实现。

1.domain实体类

有了api和返回的数据我们可以很快的建立其对应的实体类,android studio用户推荐使用GsonFormat。由于实体类的参数比较多,这里不再贴出,有兴趣的可以查看Demo

2.model数据层

ImageLsitModel,调用实现里面的接口回调,并且传入页码参数。

public interface ImageListModel {
void getImageNewList(int page,ImageListModelImpl.OnImageNewLoadListenter listenter);
}

ImageListModelImpl,实现ImageLsitModel,并且声明接口OnImageNewLoadListenter

当成时返回 image对象(就是是一个list),失败时返回错误的原因。

public interface OnLoadImageListener {
void onSuccess(HenuImage image);

void OnFaild(String str);

}

在实现ImageListModel的方法中完成数据的获取,你可以使用自己认为比较合理的方式来实现,如RxJava+Retrofit,为了方便大家理解mvp我们直接使用okhttp来实现。

package com.flyou.seen.flyouseen.ImageList.model;

import com.google.gson.Gson;
import com.flyou.seen.flyouseen.ImageList.domain.ImageNews;
import com.flyou.seen.flyouseen.comm.APi;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import java.util.List;

import okhttp3.Call;

/**

  • ============================================================

  • 项目名称:HotWXReading

  • 包名称:com.liuyajuan.login.hotwxreading.ImageList.model

  • 文件名:ImageListModelImpl

  • 类描述:

  • 创建人:flyou

  • 邮箱:fangjaylong@gmail.com

  • 创建时间:2016/3/15 15:36

  • 修改备注:

  • 版本:@version V1.0

  • ============================================================
    **/
    public class ImageListModelImpl implements ImageListModel {

    @Override
    public void getImageNewList(int page, final OnImageNewLoadListenter listenter) {
    OkHttpUtils
    .get()
    .url(APi.IMAGE_NEW_LIST_URL + "page=" + page)
    .build()
    .execute(new StringCallback() {
    @Override
    public void onError(Call call, Exception e) {
    listenter.onFailed(e.getMessage(), e);
    }

                  @Override
                  public void onResponse(String response) {
                      try {
                          String json = response.split("\\(")[1].split("\\)")[0];
                          ImageNews imageNews = new Gson().fromJson(json, ImageNews.class);
                          listenter.onSuccess(imageNews.getData());
                      }
                    catch (Exception e){
    
                    }
    
                  }
              });
    

    }

    public interface OnImageNewLoadListenter {
    void onSuccess(List<ImageNews.DataEntity> imageNews);
    void onFailed(String msg, Exception e);
    }
    }

3.View 界面展示层

ImageNewsView,主要提供界面交互需要的接口,一般为:

showLoading();显示进入条等加载界面

hideLoading();隐藏进度条等

showloadFailed();显示加载错误界面

getImageNew(object obj)获取数据并显示

这次Demo的View如下:

public interface HenuImageView {
void showLoading();
void hideLoading();
void GetImage(HenuImage henuImage);
void showLoadFaild(String str);
}

4.Presenter层,负责View和Model的交互和调度

ImgaeNewPresenter

public interface ImgaeNewPresenter {
void getImageList(int page);
}

ImageNewPresenterImpl

实现ImgaeNewPresenter和ImageListModelImpl.OnImageNewLoadListenter,在构造方法中完成View(activity实现) 和Model的初始化。

在getImageList()中loadingView可见,并且执行Modele层的数据获取操作

在onSuccess()中将loadingVeiw隐藏,并且将获取到的数据回调给view的实现类。

在onFailed()中将loadingVeiw隐藏,并且msg传给view的实现类。

public class ImageNewPresenterImpl implements ImgaeNewPresenter, ImageListModelImpl.OnImageNewLoadListenter {
private ImageNewsView mImageNews;
private ImageListModelImpl mImageListModel;
public ImageNewPresenterImpl(ImageNewsView imageNews) {
this.mImageListModel = new ImageListModelImpl();
this.mImageNews = imageNews;

}



@Override
public void getImageList(int page) {

    mImageNews.showLoading();
    mImageListModel.getImageNewList(page, this);
}

@Override
public void onSuccess(List<ImageNews.DataEntity> imageNews) {
    mImageNews.hideLoading();
    mImageNews.addImage(imageNews);
}

@Override
public void onFailed(String msg, Exception e) {
    mImageNews.hideLoading();
    mImageNews.shwoLoadFaild(msg);
}

}

5.Activity 界面展示

实现View层的接口,初始化persenter,调用persenterimpl的方法完成数据的获取。

在activity中:

private ImgaeNewPresenter mImageNewPresenter;

public class MainActivity extends BaseActivity implements ImageNewsView{

@Override

onceate(){

初始化presenter

mImageNewPresenter = new ImageNewPresenterImpl(this);
mImageNewPresenter.getImageList(currentPage);

}

@Override
public void showLoading() {

//显示加载界面
loadingView.setVisibility(View.VISIBLE);
}

@Override
public void addImage(List<ImageNews.DataEntity> imageNewList) {

//界面展示
}

}
@Override
public void hideLoading() {
//隐藏加载界面
}

@Override
public void shwoLoadFaild() {

//显示获取数据错误界面
}

}

这样一个简单的mvp功能就实现,数据层和View层完全分开了,这样在进行单元测试时就很方便了。

总结:mvp实际上就是将以前activity中复杂的数据获取和传递的过程抽离了出来,让Model来完成,persenter负责view和model的交互和数据的传递,将数据和视图分割开来,互不干扰,是项目的结构更加的清晰。

有什么我写的不妥的地方,欢迎大家指正!

查看原文

posted @ 2016-03-22 10:57  Mosthink  阅读(108)  评论(0编辑  收藏  举报