手写Rxjava+Retrofit+Mvp

本文介绍了如何手写Rxjava、Retrofit和Mvp框架,详细讲解了Mvp的各组成部分,包括Model层的Disposable管理、异常处理、Presenter的创建以及MvpActivity的实现。通过这篇文章,读者可以了解到搭建Mvp框架的全过程,并能实际应用到项目中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

手写Rxjava+Retrofit+Mvp

今天来写写我的第一篇博客,分享一下自己手写的Rxjava+Retrofit+Mvp,帮助大家学习,要是有哪些写的不好的地方可以提出来,我虚心接受。

关于什么是Rxjava和Retrofit,两者结合的好处我这里就不在一一概述了,网上有很多大牛写的都很好,这里推荐几篇比较好的博文,大家可以去参考一下,一篇是扔物线大牛写的给Android 开发者的RxJava 详解Android 优雅的让RxJava2.0+Retrofit2.0结合使用。先附上gradle的依赖,以免到时候小伙伴们找到的类会有偏差。

 //rxjava +retrofit
    implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//配合rxjava2
    implementation 'com.squareup.okhttp3:logging-interceptor:3.8.1'//拦截器

本文重点讲述的事如何搭建mvp框架,因为自己比较喜欢架构这一块,尤其是mvp设计模式,简单明了的代码风格和清晰的体系结构受广大程序员的喜欢,最近有去研究了这个模式,加了一些自己的理解,下面就把自己所感所悟分享出来,有哪些写的不好的地方和错误欢迎指出。

什么是mvp

先上个图方便大家的理解
这里写图片描述
mvp(model view presenter)是一种设计模式,在mvc(model view controller)的基础上进行了优化,使得在代码结构上非常的干净和整洁,mvp和mvc相比,mvc的View,controller和model全都写在一个activity里,我相信很多老的android应用应该都是这样写的,这样写的代码比较臃肿,会造成一个界面产生几千行代码的可能,维护起来非常的困难。而mvp架构在代码风格上就完胜mvc,它把View和Model这两块抽离出来,放在单独的模块里,通过presenter这个对象进行交互,降低了代码的耦合度。

一.什么是model

model英文翻译过来就是数据模型,像我们平日里通过网络请求得到的json数据要通过一个实体类进行保存,这个实体类就是我们所说的model数据模型,里面包含业务逻辑这块。当然model你也可以这么去理解,他是获取网络数据的一个类。

如何搭建model层

一.搭建Disposable管理类
1.定义Disposable接口
package com.lcp.lcplibrary.mvp.disposable;

import io.reactivex.disposables.Disposable;

/**
 * Created by lcp on 2018/6/16.
 */
public interface IDisposable {
    //添加
    void add(Disposable subscription);
    //取消
    void cancel(Disposable t);
    //取消所有
    void cancelall();
}
2.定义一个Disposable的实现类DisposableManager
package com.lcp.lcplibrary.mvp.disposable;

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;

/**
 * Created by lcp on 2018/6/16.Disposable管理类
 */
public class DisposableManager implements IDisposable {
    private static DisposableManager subscriptionManager;
    private CompositeDisposable mDisposables;

    private DisposableManager() {
        if (mDisposables == null) {
            mDisposables = new CompositeDisposable();
        }
    }

    @Override
    public void add(Disposable disposable) {
        if (disposable == null) return;
        mDisposables.add(disposable);
    }

    @Override
    public void cancel(Disposable disposable) {
        if (mDisposables != null) {
            mDisposables.delete(disposable);
        }
    }

    @Override
    public void cancelall() {
        if (mDisposables != null) {
            mDisposables.clear();
        }
    }

    public static DisposableManager getInstance() {
        if (subscriptionManager == null) {
            subscriptionManager = new DisposableManager();
        }
        return subscriptionManager;
    }
}
二.定义异常处理类
package com.lcp.lcplibrary.mvp.error;

/**
 * Created by lcp on 2018/6/16.错误信息的实体类
 */
public class ErrorBodyDTO {
    private String errCode;
    private String errMsg;

    public String getErrCode() {
        return errCode;
    }

    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }

    public String getErrMsg() {
        return errMsg;
    }

    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
package com.lcp.lcplibrary.mvp.error;

import android.net.ParseException;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;

import org.json.JSONException;

import java.io.IOException;
import java.net.ConnectException;

import okhttp3.ResponseBody;
import retrofit2.HttpException;

/**
 * Created by lcp on 2018/6/16.异常处理类
 */
public class ExceptionHandle {
    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;
    private static final int FAIL_QUEST = 406;//无法使用请求的内容特性来响应请求的网页
    private static final int BAD_REQUEST = 400;
    private static ResponseBody body;

    public static ResponeThrowable handleException(Throwable e) {
        ResponeThrowable ex;
        if (e instanceof HttpException) {
            HttpException httpException = (HttpException) e;
            ex = new ResponeThrowable(e, ERROR.HTTP_ERROR);
            switch (httpException.code()) {
                case UNAUTHORIZED:
                    break;
                case FORBIDDEN:
                    ex.message = "服务器已经理解请求,但是拒绝执行它";
                    break;
                case NOT_FOUND:
                    ex.message = "服务器异常,请稍后再试";
                    break;
                case REQUEST_TIMEOUT:
                    ex.message = "请求超时";
                    break;
                case GATEWAY_TIMEOUT:
                case INTERNAL_SERVER_ERROR:
                    ex.message = "服务器遇到了一个未曾预料的状况,无法完成对请求的处理";
                    break;
                case BAD_REQUEST:
                    break;
                case BAD_GATEWAY:
                case SERVICE_UNAVAILABLE:
                case FAIL_QUEST:
                    body = ((HttpException) e).response().errorBody();
                    try {
                        String message = "";
                        if (body != null) {
                            message = body.string();
                        }
                        Gson gson = new Gson();
                        ErrorBodyDTO globalExceptionDTO = gson.fromJson(message, ErrorBodyDTO.class);
                        if (globalExceptionDTO.getErrMsg() != null) {
                            ex.message = globalExceptionDTO.getErrMsg();
                        } else {
                            ex.message = "";
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    break;
                default:
                    ex.message = "网络错误";
                    break;
            }
            return ex;
        } else if (e instanceof ServerException) {
            ServerException resultException = (ServerException) e;
            ex = new ResponeThrowable(resultException, resultException.code);
            ex.message = resultException.message;
            return ex;
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            ex = new ResponeThrowable(e, ERROR.PARSE_ERROR);
            ex.message = "解析错误";
            return ex;
        } else if (e instanceof ConnectException) {
            ex = new ResponeThrowable(e, ERROR.NETWORD_ERROR);
            ex.message = "连接失败";
            return ex;
        } else if (e instanceof javax.net.ssl.SSLHandshakeException) {
            ex = new ResponeThrowable(e, ERROR.SSL_ERROR);
            ex.message = "证书验证失败";
            return ex;
        } else if (e instanceof java.net.SocketTimeoutException) {
            ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
            //ex.message = "连接超时";
            ex.message = "当前网络连接不顺畅,请稍后再试!";
            return ex;
        } else if (e instanceof java.net.UnknownHostException) {
            ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
            ex.message = "网络中断,请检查网络状态!";
            return ex;
        } else if (e instanceof javax.net.ssl.SSLException) {
            ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
            ex.message = "网络中断,请检查网络状态!";
            return ex;
        } else if (e instanceof java.io.EOFException) {
            ex = new ResponeThrowable(e, ERROR.PARSE_EmptyERROR);
            ex.message = "1007";
            return ex;
        } else if (e instanceof NullPointerException) {
            ex = new ResponeThrowable(e, ERROR.PARSE_EmptyERROR);
            ex.message = "数据为空,显示失败";
            return ex;
        } else {
            ex = new ResponeThrowable(e, ERROR.UNKNOWN);
            ex.message = "未知错误";
            return ex;
        }
    }


    /**
     * 约定异常
     */
    private class ERROR {
        /**
         * 未知错误
         */
        private static final int UNKNOWN = 1000;
        /**
         * 解析错误
         */
        private static final int PARSE_ERROR = 1001;
        /**
         * 解析no content错误
         */
        private static final int PARSE_EmptyERROR = 1007;
        /**
         * 网络错误
         */
        private static final int NETWORD_ERROR = 1002;
        /**
         * 协议出错
         */
        private static final int HTTP_ERROR = 1003;

        /**
         * 证书出错
         */
        private static final int SSL_ERROR = 1005;

        /**
         * 连接超时
         */
        private static final int TIMEOUT_ERROR = 1006;

        private static final int LOGIN_ERROR = -1000;
        private static final int DATA_EMPTY = -2000;


    }

    public static class ResponeThrowable extends Exception {
        private int code;
        public String message;

        private ResponeThrowable(Throwable throwable, int code) {
            super(throwable);
            this.code = code;
        }

        private ResponeThrowable(String message, int code) {
            this.code = code;
            this.message = message;
        }
    }

    private class ServerException extends RuntimeException {
        private int code;
        private String message;

        private ServerException(int code, String message) {
            this.code = code;
            this.message = message;
        }
    }

}
三.搭建Model层
1.搭建BaseModel

在这个类里进行对象的订阅,被观察者订阅观察者

package com.lcp.lcplibrary.mvp.model;


import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by lcp on 2018/6/13.订阅
 */
public class BaseModel<T> {

    public void subscribe(Observable<T> observable, Observer<T> observer) {
        observable
                //请求完成后在主线程更新UI
                .observeOn(AndroidSchedulers.mainThread())
                //请求数据的时间发生在io线程
                .subscribeOn(Schedulers.io())
                .subscribe(observer);
    }
}

定义泛型T,为你要生成的实体类。

2.建立一个Observer实现类去实现io.reactivex.Observer接口

重写onSubscribe,onNext和onError回调方法,自行处理返回的数据

package com.lcp.lcplibrary.mvp.model;

import com.lcp.lcplibrary.mvp.error.ExceptionHandle;

import io.reactivex.disposables.Disposable;

/**
 * Created by lcp on 2018/6/16.观察者
 */
public abstract class MyObServer<T> implements io.reactivex.Observer<T> {
    @Override
    public void onSubscribe(Disposable d) {
        OnDisposable(d);
    }

    @Override
    public void onNext(T t) {
        OnSuccess(t);
    }

    @Override
    public void onError(Throwable e) {
        //自定义异常的传递
        OnFail(ExceptionHandle.handleException(e));
        Onfinish();
    }

    @Override
    public void onComplete() {
        Onfinish();
    }

    public abstract void OnSuccess(T t);

    public abstract void OnFail(ExceptionHandle.ResponeThrowable e);

    public abstract void Onfinish();

    public abstract void OnDisposable(Disposable d);

}
  • 通过泛型T,可以随机改变你想要的类型,传入什么类型,得到的就是什么类型
  • 定义四个抽象方法OnSuccess,OnFail,Onfinish,OnDisposable,在onSubscribe,onComplete,onNext和onError回调时使用,让MyObserver的实现类去重写方法
  • 相当于给Observer做了一层封装

    二.什么是View

    View英文翻译过来是视图的意思,在mvp里面它所担当的角色是界面上的显示效果,比如网络开始请求时,你要显示弹窗,网络结束时你要结束弹窗,网络错误时你要显示Toast,这些都是View上的东西,说白了就是Ui线程上所要做的操作。

    如何搭建View层

    一.定义一个自己所需要的View
    1.写一个BaseView接口IBaseView

    我这里就简单定义两个方法,一个是显示弹窗,一个是消失。

package com.lcp.lcplibrary.mvp.view;

/**
 * Created by lcp on 2018/6/12.界面数据加载的处理
 */
public interface IBaseView {
    void showLoading();

    void dismissLoading();
}
2.定义一个IMvpView,去继承IBaseView
package com.lcp.lcplibrary.mvp.view;


/**
 * Created by lcp on 2018/6/12 0011.数据加载的回调方法
 */

public interface IMvpView<T> extends IBaseView {
    void onSuccess(T t);

    void onfailed(String msg);
}
  • 通过泛型,拿到自己想要的实体类

三.什么是presenter

presenter其实就是model和View的中介,mvp中的核心其实就是presenter,这也是和mvc最大的区别,mvc没有了controller,view和model照样可以进行交互,而mvp没有了presenter,view和model是不能进行交互的。总之presenter是mvp里比较重要的一块内容。

如何搭建presenter

一.搭建主Presenter接口

在这里接口里定义presenter的生命周期

package com.lcp.lcplibrary.mvp.presenter;

/**
 * Created by lcp on 2018/6/12.主Presenter接口,Presenter的生命周期
 */
public interface IBasePresenter<V> {
    void onCreate();

    void onDestory();

    void attachView(V v);

    void detachView();
}
二.定义一个IBasePresenter的实现类

整个mvp架构的核心部分

package com.lcp.lcplibrary.mvp.presenter;

import com.lcp.lcplibrary.mvp.disposable.DisposableManager;
import com.lcp.lcplibrary.mvp.error.ExceptionHandle;
import com.lcp.lcplibrary.mvp.model.BaseModel;
import com.lcp.lcplibrary.mvp.model.MyObServer;
import com.lcp.lcplibrary.mvp.view.IMvpView;

import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;


/**
 * Created by lcp on 2018/6/11 0011.主presenter的实现类,用来处理view和model之前的交互
 */

public class BasePresenter<T, V extends IMvpView<T>> implements IBasePresenter<V> {

    private BaseModel<T> mbaseModel;
    private V mbaseView;

    public BasePresenter() {
    }

    public void getData(Observable<T> observable) {
        mbaseView.showLoading();
        mbaseModel.subscribe(observable, new MyObServer<T>() {

            @Override
            public void OnSuccess(T t) {
                mbaseView.onSuccess(t);
            }

            @Override
            public void OnFail(ExceptionHandle.ResponeThrowable e) {
                mbaseView.onfailed(e.message);
            }

            @Override
            public void Onfinish() {
                mbaseView.dismissLoading();
            }

            @Override
            public void OnDisposable(Disposable d) {
                DisposableManager.getInstance().add(d);
            }
        });
    }

    @Override
    public void onCreate() {
        mbaseModel = new BaseModel<>();
    }

    @Override
    public void onDestory() {
        cancelAll();
    }


    @Override
    public void attachView(V v) {
        mbaseView = v;
    }

    private void cancelAll() {
        DisposableManager.getInstance().cancelall();
    }


    @Override
    public void detachView() {
        mbaseView = null;
    }
}
  • 定义泛型,层层嵌套,约束类型
  • 重写方法,在生命周期里进行对象的创建和销毁
  • 在getData方法里实现model和View的交互,最后把数据传递给外部

四.MvpActivity

它作为所有想实现mvp体系的Activity的基类,搭建它是为了以后快速的实现

如何搭建MvpActivity

一.建立BaseActivity

大家在项目中经常用到的基类,我这里简单写两个方法

package com.lcp.lcplibrary.mvp.view;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.annotation.Nullable;

/**
 * Created by lcp on 2018/6/28.activity的基类
 */
public class BasicActivity extends Activity {
    private ProgressDialog progressDialog;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void showLoading() {
        if (progressDialog == null) {
            progressDialog = new ProgressDialog(this);
        }
        progressDialog.setMessage("加载中");
        progressDialog.show();
    }

    public void dismissLoading() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }
}
二.搭建抽象类MvpActivity
package com.lcp.lcplibrary.mvp.view;

import android.os.Bundle;
import android.support.annotation.Nullable;

import com.lcp.lcplibrary.mvp.presenter.IBasePresenter;

/**
 * Created by lcp on 2018/6/13.
 */
public abstract class MvpActivity<T, V extends IMvpView<T>, P extends IBasePresenter<V>> extends BasicActivity {

    public P presenter;
    private V view;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (presenter == null) {
            presenter = createPresenter();
        }
        if (view == null) {
            view = createView();
        }
        if (presenter != null && view != null) {
            presenter.attachView(view);
        }
        if (presenter != null) {
            presenter.onCreate();
        }

        //设置布局
        setContentView(layoutId());
        //加载本地数据
        initData();
        //初始化Ui
        initView();
        //加载网络数据
        initWeb();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (presenter != null) {
            presenter.detachView();
            presenter.onDestory();
        }
    }

    protected abstract P createPresenter();

    protected abstract V createView();

    protected abstract int layoutId();

    protected abstract void initView();

    protected abstract void initWeb();

    protected abstract void initData();
}
  • 泛型的定义和BasePresenter相同
  • 在onCreate方法里实现初始化操作,创建抽象方法,在onCreate里调用,让子类重写
  • 在onDestroy里释放内存

五.Mvp框架的使用

以上是搭建mvp框架的过程,现在可以开始使用了

package com.lcp.lcplib.ui;

import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.lcp.lcplib.R;
import com.lcp.lcplib.service.manager.DataManager;
import com.lcp.lcplib.service.model.Book;
import com.lcp.lcplibrary.mvp.presenter.BasePresenter;
import com.lcp.lcplibrary.mvp.view.IMvpView;
import com.lcp.lcplibrary.mvp.view.MvpActivity;

import java.util.HashMap;

public class MainActivity extends MvpActivity<Book,IMvpView<Book>,BasePresenter<Book,IMvpView<Book>>> implements IMvpView<Book> {

    private TextView text;

    @Override
    protected BasePresenter<Book, IMvpView<Book>> createPresenter() {
        return new BasePresenter<>();
    }

    @Override
    protected IMvpView<Book> createView() {
        return this;
    }

    @Override
    protected int layoutId() {
        return R.layout.activity_main2;
    }

    @Override
    protected void initView() {
        text = (TextView) findViewById(R.id.text);
    }

    @Override
    protected void initWeb() {

    }

    @Override
    protected void initData() {
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("q","金瓶梅");
                map.put("tag","");
                map.put("start",0);
                map.put("count",1);
                presenter.getData(DataManager.getInstance().getSearchbook(map));
            }
        });
    }

    @Override
    public void onSuccess(Book book) {
        text.setText(book.getBooks().get(0).getAlt_title());
    }

    @Override
    public void onfailed(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

}

在你要实现Mvp框架的Activity里,继承MvpActivity,实现View的接口,传入你想要的类型就可以实现了。

总结

  • 以上就是自己搭建的mvp框架,我已经把相同的部分抽到一个库里,有需要的小伙伴直接使用即可
  • 在MvpActivity搭建这块泛型设计我觉得有些繁琐,如果知道如何优化的大牛们欢迎私信我。
  • 最后附上源码https://github.com/laichangp/lcplib_觉得不错的小伙伴可以点个星哈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值