使用Retrofit+RxJava搭建简单的MVP网络请求框架

首先感谢蛇发女妖,偶尔在简书翻到这篇文章,很多地方都是借鉴这位的思想
另外感谢Season_zlc,大神的水管图很传神,刚接触RxJava的同学可以看看,撸完差不多也可以跟我一样简单使用了

老生常谈先介绍下MVC和MVP,先整张图
这里写图片描述

MVC:Android其实本身就是MVC模式,实现了视图于代码分离,视图是用XML画出来的,然后在Activity实现各种功能,作为一个开发者这是最简单的实现模式,除了视图外,各种封装model内的数据逻辑,以至于往往写了一个万能的Activity,,,

MVP:MVP是MVC的延伸,现在越来越多的开发者使用MVP框架,自然有他的优势,主要优势就体现在View和Model完全分离,即使我们修改了Model也不影响View的展现,View和Model所有的交互都有Presenter完成,View不参与交互,只注重视图及功能的实现

实现MVP步骤(个人感觉):
第一步Model,先构建数据层
第二步View,在实现视图层
第三步Presenter,最后使用Presenter进行交互

先看下我这个简单的MVP架构

这里写图片描述

我们就以上述步骤进行:
构建Model

Model就是数据模型,既然是数据模型那么就应该有数据,怎么获取数据呢,这就需要用到网络请求了,所以我们先写个简单的网络请求框架

网络请求我用的是Retrofit,在使用Retrofit之前先把依赖加上去

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.okhttp3:okhttp:3.8.1'
    compile 'io.reactivex:rxandroid:1.2.0'

网络这块分了两部分写,一个是类一个是接口,接口(NetWorkRequestService)方面就十分简单了,主要就是实现接口访问网络,官方写法没什么改变,主要就是加了rxjava,只是把Call换成了Observable这里我请求的是豆瓣电影Top250

public interface NetWorkRequestService {
    @GET("movie/top250")
    Observable<MovieInfo> getMovie(@Query("start") int start, @Query("count") int count);
}

我们再看类(NetWorkHelper),这里主要增加了一个是静态实例,主要用于Model使用

    private Retrofit mRetrofit;

    private String BASEURL = "https://api.douban.com/v2/";

    private static NetWorkHelper netWorkHelperInstance = null;
    //实例用于Model调用
    public static NetWorkHelper getInstance() {
        if (netWorkHelperInstance == null) {
            netWorkHelperInstance = new NetWorkHelper();
        }
        return netWorkHelperInstance;
    }
    //构造器
    public NetWorkHelper() {
        initRetrofit();
    }

    //Retrofit设置
    private Retrofit initRetrofit() {
        mRetrofit = new Retrofit.Builder()
                .baseUrl(BASEURL)
              .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return mRetrofit;
    }

    //将方法抽离,避免代码冗余
    public NetWorkRequestService getSersver() {
        return mRetrofit.create(NetWorkRequestService.class);
    }

然后写Model,Model主要是调用网络请求数据,实现代码如下

    NetWorkRequestService netWorkRequestService;
    //获取netWorkRequestService
    public MovieModel() {
        netWorkRequestService = NetWorkHelper.getInstance().getSersver();
    }
    //这里写的是固定返回5条数据
    public Observable<MovieInfo> getRequestMovieData() {
        return netWorkRequestService.getMovie(0,5);
    }

然后写View,View我也分成了两个,一个是父View,一个是具体实现的View
首先先看下父View,这里主要展示了三个状态,分别为请求中,成功,失败

    /**
     * 请求中.....
     */
    void requestIng(String string);

    /**
     * 请求成功
     *
     * @param data
     */
    void requestSuccess(T data);

    /**
     * 请求失败(非网络问题,一般为后台返回失败信息)
     *
     * @param errorMessage
     */
    void requestError(String errorMessage);

然后MovieView继承父View重写方法,代码如下

    @Override
    void requestSuccess(Object data);

    @Override
    void requestIng(String string);

    @Override
    void requestError(String errorMessage);

重点看Presenter,跟View一样,我将Presenter也写了一个父Presenter,最好是按照Activity的生命周期来,这样便于我们更好的管理,我这里为了方便只写了三个方法

    void onCreat();

    void onStart(BaseView view);

    void onStop();

具体实现代码,继承父Presenter重写父类方法,然后获取Model和View,然后构建桥梁,使用Model获取数据,然后将数据分状态给View


    MovieModel movieModel;
    MovieView movieView;
    MovieInfo mMovieInfo;
    //用于解绑
    CompositeSubscription mCompositeSubscription;
    Context mContext;

    public MoviePresenter(Context context) {
        this.mContext = context;
    }

    @Override
    public void onCreat() {
        //初始化
        mMovieInfo = new MovieInfo();
        movieModel = new MovieModel();
        mCompositeSubscription = new CompositeSubscription();
    }

    @Override
    public void onStart(BaseView view) {
       //初始化View
       movieView = (MovieView) view;
    }

    @Override
    public void onStop() {
        //解绑
        if (mCompositeSubscription.hasSubscriptions()) {
            mCompositeSubscription.unsubscribe();
        }
    }

    public void setRequestData() {
        //数据请求中
        movieView.requestIng("请求中");
        mCompositeSubscription.add(movieModel.getRequestMovieData()
                .subscribeOn(Schedulers.io())
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<MovieInfo>() {
                    @Override
                    public void onCompleted() {
                        //因为没找到code值所以就直接写了
                        if (mMovieInfo != null) {
                            //数据正确时,返回数据如code等于200
                            movieView.requestSuccess(mMovieInfo);
                        } else {
                            //error包括很多种,如code值非正确时返回的错误信息
                            movieView.requestError("数据有误");
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        movieView.requestError(e.toString());
                    }

                    @Override
                    public void onNext(MovieInfo movieInfo) {
                        mMovieInfo = movieInfo;
                    }
                }));
    }

Presenter完成后工作几乎就完成了,只有在Activity中调用了,调用Presenter方法并回调View方法,具体实现代码如下:

  private TextView mbtn;
    MoviePresenter moviePresenter;
    MovieInfo movieInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        movieInfo = new MovieInfo();
        moviePresenter = new MoviePresenter(this);
        mbtn = findViewById(R.id.btn);
        moviePresenter.onCreat();
        mbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                moviePresenter.setRequestData();
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        moviePresenter.onStart(this);
    }

    @Override
    public void requestSuccess(Object data) {
        movieInfo = (MovieInfo) data;
        mbtn.setText(movieInfo.getTitle());
    }

    @Override
    public void requestIng(String string) {
        mbtn.setText(string);
    }

    @Override
    public void requestError(String errorMessage) {
        mbtn.setText(errorMessage);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        moviePresenter.onStop();
    }

效果如下图
这里写图片描述

下载地址:
CSDN下载地址
GitHub地址

最后再次感谢蛇发女妖Season_zlc两位大神

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值