学习RxJava+Retrofit+OkHttp+MVP的网络请求使用

公司的大佬用的是这一套,那我这个菜鸟肯定要学习使用了。

我在网上找了很多文章,写的都很详细,比如

https://www.jianshu.com/u/5fd2523645da

https://www.jianshu.com/p/193d8c37c73c

趁热打铁,写一篇学习笔记,理顺思路。

先把他们都引入
//rxjava
compile 'io.reactivex.rxjava2:rxjava:2.2.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.2'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' //retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0' //okhttp
compile 'com.squareup.okhttp3:okhttp:3.11.0'
compile 'com.squareup.okio:okio:1.14.0'
   implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
    //gson 
implementation 'com.google.code.gson:gson:2.8.4' implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

一、RxJava学习

简单的说,核心是观察者模式。那么这个就很有意思了,举个栗子

学习RxJava+Retrofit+OkHttp+MVP的网络请求使用

我订阅了公众号之后就可以去干其他的事了,当公众号有新的文章之后发个消息通知我:有新文章了。这时我再点开去查看。

RxJava中有这几种方法

onNext():一直向我推送文章
onComplete():文章推送完了
onError():推送出现异常,同时终止,不再有消息发出.
onSubscribe():RxJava 2.0 中新增的,传递参数为Disposable,可用于切断接收事件

RxJava的链式操作

Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
})
.observeOn(AndroidSchedulers.mainThread())//回调在主线程
.subscribeOn(Schedulers.io())//执行在io线程
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
} @Override
public void onNext(Integer value) {
Log.d(TAG, "onNext=" + value);
} @Override
public void onError(Throwable e) {
Log.d(TAG, "onError");
} @Override
public void onComplete() {
Log.d(TAG, "onComplete");
}
});

线程切换流程(observeOn与subscribeOn)

当前为主(main)线程,订阅(向上走)

1.开始 subscribe 订阅

2.经 subscribeOn 将线程切换为IO线程(Schedulers:线程调度器)

3.经 observeOn 控制数据流的,跳过

4.经 create 在IO线程中执行

到这里,订阅完成,开始发射数据。

当前为IO线程,发射数据(向下走)

1.经 observeOn 将线程切换为主(main)线程

2.经 subscribeOn 控制订阅的,跳过

3.经 onNext 在主线程中执行

整个流程就走完了。

RxJava还有很多操作符,等后面慢慢学习。

二、Retrofit学习

简单的说,它是网络适配器,通过OkHttp发送请求

它是将okhttp进行了进一步的封装翻新

偷张图哈哈哈 https://www.jianshu.com/p/15edb4de0f62

学习RxJava+Retrofit+OkHttp+MVP的网络请求使用

三、进入正题,打通网络请求

1.Retrofit封装

创建Api接口

public interface IApiService {
@POST("/lay-eggs/androidtest.php")
Observable<TestBean> getData(@Query("time") String time);
}

也可以用@QueryMap 直接整一个集合上去。

TestBean用JsonFormat自动生成

学习RxJava+Retrofit+OkHttp+MVP的网络请求使用

创建Retrofit管理类

public class RetrofitManager {
private static RetrofitManager retrofitManager;
private Retrofit retrofit;
private static final String BASE_URL="http://yyyxuan.cn";//根地址
private IApiService apiService; /**
* 单例模式
* @return
*/
public static RetrofitManager getInstance (){
if (retrofitManager==null){
synchronized (RetrofitManager.class){
if (retrofitManager==null){
retrofitManager= new RetrofitManager();
}
}
}
return retrofitManager;
} //构造函数
private RetrofitManager(){
initRetrofitManager();
} //创建Retrofit实例
private void initRetrofitManager() {
retrofit=new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())//对服务器数据进行解析
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//RxJava适配器
.build();
apiService=retrofit.create(IApiService.class);
} public IApiService apiservice(){return apiService;} }

2.订阅关系处理

定义添加删除订阅关系的接口

public interface SubscriptionHelper<T> {

    /**
* 添加
* @param disposable
*/
void add(Disposable disposable); /**
* 取消
* @param disposable
*/
void cancel(Disposable disposable); /**
* 取消所有
*/
void cancelAll();
}

创建订阅关系管理类

public class SubscriptionManager implements SubscriptionHelper<Object> {

    public static SubscriptionManager subscriptionManager;
private CompositeDisposable mDisposables;//存放disposable容器 /**
* 构造函数 new CompositeDisposable对象
*/
public SubscriptionManager(){
if (mDisposables==null){
mDisposables=new CompositeDisposable();
}
} /**
* 单例
* @return
*/
public static SubscriptionManager getInstance(){
if (subscriptionManager==null){
synchronized (SubscriptionManager.class){
if (subscriptionManager==null){
subscriptionManager=new SubscriptionManager();
}
}
}
return subscriptionManager;
} /**
* 订阅事件加入到CompositeDisposable容器中
* @param disposable 订阅事件
*/
@Override
public void add(Disposable disposable) {
if(disposable==null) return;
mDisposables.add(disposable);
} /**
* 取消订阅事件
* @param disposable 订阅事件
*/
@Override
public void cancel(Disposable disposable) {
if (disposable!=null){
mDisposables.delete(disposable);
}
} /**
* 清除容器所有
*/
@Override
public void cancelAll() {
if (mDisposables!=null){
mDisposables.clear();
}
}
}

3.异常处理

网上有很多异常处理的类,可以去搜一下(忘记我看的哪篇文章了)

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; public static ResponseException handleException(Throwable e){ //转换成ResponseException,根据状态码判定错误信息
ResponseException ex;
if(e instanceof HttpException){
HttpException httpException=(HttpException)e;
/**
* 传入状态码,根据状态码判定错误信息
*/
ex=new ResponseException(e,ERROR.HTTP_ERROR);
switch (httpException.code()){
case UNAUTHORIZED:
ex.message="未验证";
break;
case FORBIDDEN:
ex.message="服务禁止访问";
break;
case NOT_FOUND:
ex.message="服务不存在";
break;
case REQUEST_TIMEOUT:
ex.message="请求超时";
break;
case GATEWAY_TIMEOUT:
ex.message="网关超时";
break;
case INTERNAL_SERVER_ERROR:
ex.message="服务器内部错误";
break;
case BAD_GATEWAY: break;
case SERVICE_UNAVAILABLE:
break;
default:
ex.message = "网络错误";
break;
}
return ex;
}else if(e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException){
ex=new ResponseException(e,ERROR.PARSE_ERROR);
ex.message="解析错误";
return ex;
}else if(e instanceof ConnectException){
ex=new ResponseException(e,ERROR.NETWORD_ERROR);
ex.message="连接失败";
return ex;
}else if(e instanceof javax.net.ssl.SSLHandshakeException){
ex=new ResponseException(e,ERROR.SSL_ERROR);
ex.message="证书验证失败";
return ex;
}else {
ex=new ResponseException(e,ERROR.UNKNOWN);
ex.message="未知错误";
return ex;
} } /**
* 约定异常
*/
public static class ERROR{
/**
* 自定义异常
*/
private static final int UNAUTHORIZED = 401;//请求用户进行身份验证
private static final int UNREQUEST=403;//服务器理解请求客户端的请求,但是拒绝执行此请求
private static final int UNFINDSOURCE=404;//服务器无法根据客户端的请求找到资源
private static final int SEVERERROR=500;//服务器内部错误,无法完成请求。
/**
* 协议出错
*/
public static final int HTTP_ERROR = 1003;
/**
* 未知错误
*/
public static final int UNKNOWN = 1000;
/**
* 解析错误
*/
public static final int PARSE_ERROR = 1001;
/**
* 网络错误
*/
public static final int NETWORD_ERROR = 1002;
/**
* 证书出错
*/
public static final int SSL_ERROR = 1005;
} /**
* 自定义Throwable
*/
public static class ResponseThrowable extends Exception{
public int code;
public String message;
public ResponseThrowable(Throwable throwable,int code){
super(throwable);
this.code=code;
}
} /**
* 服务器异常
*/
public class ServerException extends RuntimeException{
public int code;
public String message;
} /**
* 统一异常类,便于处理
*/
public static class ResponseException extends Exception{
public int code;
public String message;
public ResponseException (Throwable throwable,int code){
super(throwable);
this.code=code;
}
} }

4.Observer封装

上面讲到了四个方法以及他们的作用,这里简单的封装一下

public abstract class Observer<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));
} @Override
public void onComplete() {
OnCompleted();
} protected abstract void OnDisposable(Disposable d); protected abstract void OnSuccess(T t); protected abstract void OnFail(ExceptionHandle.ResponseException e); protected abstract void OnCompleted();
}

5.MVP搭建

学习RxJava+Retrofit+OkHttp+MVP的网络请求使用

网上找了很详细的图解

View:负责绘制UI元素、与用户进行交互。

Model:负责存储、检索、操纵数据。

Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。

M与V层需要P层来进行通信。

Model层

添加订阅关系,进行网络请求。

public class TestModel {
public void getTestInfo(String time, Observer<TestBean> observer){
RetrofitManager.getInstance().apiservice().getData(time)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(observer);
}
}

各种基类的封装

P层 用来绑定和解除与v层关系

public class BasePresenter<V extends BaseView> {
public V view; /**
* 添加view
* @param v
*/
public void addView(V v){
this.view=v;
} /**
* 解除
*/
public void breakView(){
if (view!=null){
view=null;
}
}
}

V层 定义回调功能,可根据不同需求更改

public interface BaseView {

    /**
* 成功回调
* @param object
*/
void onSuccess(Object object); /**
* 失败回调
* @param t 异常
*/
void onFail(ExceptionHandle.ResponseException t); /**
* 发射结束
*/
void onCompleted();
}

activity基类

public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView {
public Context context;
protected P presenter; //获取P层
protected abstract P createPresenter();
//获取是哪个activity
protected abstract int getLayoutId(); @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context=this;
setContentView(getLayoutId());
presenter=createPresenter();
presenter.addView(this);//绑定view
initView();
initData();
} public void initData(){ }; public void initView(){ }; @Override
protected void onDestroy() {
super.onDestroy();
if (presenter != null) {
presenter.breakView();
SubscriptionManager.getInstance().cancelAll();
}
}
}

真正的Presenter

public class TestPresenter extends BasePresenter<BaseView> {
private TestModel testModel;
/**
* 绑定M层
*/
public TestPresenter (){
testModel=new TestModel();
} public void test(String time){
//网络请求,创建观察者
testModel.getTestInfo(time, new Observer<TestBean>() {
@Override
protected void OnDisposable(Disposable d) {
SubscriptionManager.getInstance().add(d);
} @Override
protected void OnSuccess(TestBean testBean) {
view.onSuccess(testBean);
} @Override
protected void OnFail(ExceptionHandle.ResponseException e) {
view.onFail(e);
} @Override
protected void OnCompleted() {
view.onCompleted();
}
});
}
}

真正的Activity

public class MainActivity extends BaseActivity<TestPresenter> implements BaseView {
String TAG="aaa";
TextView textView;
Button button; /**
* 绑定p层
* @return
*/
@Override
protected TestPresenter createPresenter() {
return new TestPresenter();
} /**
* 加载当前activity
* @return
*/
@Override
protected int getLayoutId() {
return R.layout.activity_main;
} /**
* 成功回调
* @param object
*/
@Override
public void onSuccess(Object object) {
Log.d(TAG, "onSuccess: "+beanToJson(object));
TestBean testBean= (TestBean) object;
textView.setText(testBean.getData().getContent());
} /**
* 失败回调
* @param t 异常
*/
@Override
public void onFail(ExceptionHandle.ResponseException t) {
Log.d(TAG, t.message.toString());
} @Override
public void onCompleted() { } public String beanToJson(Object bean) {
Gson gson = new Gson();
String jsonStr = gson.toJson(bean);
return jsonStr;
} /**
* 初始化界面
*/
@Override
public void initView() {
super.initView();
textView=findViewById(R.id.mtv);
button=findViewById(R.id.mbtn);
} /**
* 初始化数据
*/
@Override
public void initData() {
super.initData();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
presenter.test("");
}
});
}
}

别忘了最重要的网络权限(在AndroidManifest.xml)

<uses-permission android:name="android.permission.INTERNET" />

github:https://github.com/steffenx/RxJava-Retrofit-mvp

6.最后

写下这篇博客是帮助我学习,知识梳理,加深印象。以后也能翻出来看看对吧(狗头)

上一篇:TimePicker控件、帧动画、补间动画


下一篇:[UE4]逻辑状态机组件