学习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中有这几种方法
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

三、进入正题,打通网络请求
1.Retrofit封装
创建Api接口
public interface IApiService {
@POST("/lay-eggs/androidtest.php")
Observable<TestBean> getData(@Query("time") String time);
}
也可以用@QueryMap 直接整一个集合上去。
TestBean用JsonFormat自动生成

创建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搭建

网上找了很详细的图解
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.最后
写下这篇博客是帮助我学习,知识梳理,加深印象。以后也能翻出来看看对吧(狗头)
学习RxJava+Retrofit+OkHttp+MVP的网络请求使用的更多相关文章
- RxJava+Retrofit+OkHttp,一步一步封装网络框架;
使用RxJava+Retrofit+OkHttp,首先在build.gradle添加: compile 'com.squareup.okhttp3:okhttp:3.8.1' compile 'com ...
- Android使用RxJava+Retrofit2+Okhttp+MVP练习的APP
Android使用RxJava+Retrofit2+Okhttp+MVP练习的APP 项目截图 这是我的目录结构 五步使用RxJava+Retrofit2+Okhttp+RxCache 第一步 ...
- Rxjava + retrofit + dagger2 + mvp搭建Android框架
最近出去面试,总会被问到我们项目现在采用的什么开发框架,不过据我的经验网络框架(volley)+图片缓存(uIl)+数据库(orm)+mvp,不过现在这套框架比较好了,现在采用什么呢?Rxjava + ...
- 使用 RxJava 进行嵌套串行网络请求的一种方法
需求 有这样一个列表数据,它包含了商店+订单的信息,获取订单列表时,订单实体中会包含商店的 ID,而列表显示时需要商店的名称和 logo,这时候就需要进行嵌套串行网络请求了. 关键词 flatMap ...
- Android 的OkHttp(发送网络请求)
今天讲的是和HttpURLConnection差不多的OkHttp; 先把网站献上: 官网介绍okhttp的: https://square.github.io/okhttp/ 下载postman的: ...
- Python 学习之urllib模块---用于发送网络请求,获取数据(2)
接着上一次的内容. 先说明一下关于split()方法:它通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串(把一个字符串分割成很多字符串组成的list列表) 语法: ...
- 浅谈我为什么选择用Retrofit作为我的网络请求框架
比较AsyncTask.Volley.Retrofit三者的请求时间 使用 单次请求 7个请求 25个请求 AsyncTask 941ms 4539ms 13957ms Volley 560ms 22 ...
- Python 学习之urllib模块---用于发送网络请求,获取数据(5)
查询城市天气最后一节 需要导入上一节的结果city10.py #!/usr/bin/python# -*- coding: UTF-8 -*-import urllib.requestfrom ci ...
- Python 学习之urllib模块---用于发送网络请求,获取数据(4)
承接将查询城市编码的结果保存到文件中,以字典的形式保存,目的是为了在查询某个城市的天气的时候,能够通过输入的城市名称,找到对应的城市编码.所以此结果字典的数据结构,就是city={城市名称:城市编码} ...
随机推荐
- JuiceSSH:安卓平台免费好用的 SSH 客户端
为了解决上下班路上或者没带电脑时,查看 Linux 服务器日志或者紧急运维的需求,最终找到了 JuiceSSH 这款软件,强烈推荐给大家. 简介 JuiceSSH 是一个为 Android 打造的全功 ...
- 定位new表达式与显式调用析构函数
C++的核心理念之一是RAII,Resource Acquisition Is Initialization,资源获取即初始化.资源有很多种,内存.互斥锁.文件.套接字等:RAII可以用来实现一种与作 ...
- F - Select Half dp
题目大意:从n个数里边选n/2个数,问和最大是多少. 题解:这是一个比较有意思的DP,定义状态dp[i][1],表示选了第i个数的最优状态,dp[i][0]表示没有选第i个数的最优状态. 状态是如何转 ...
- A - Number Sequence 哈希算法(例题)
Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M ...
- python圆周率计算小程序(非常慢)
源码: from math import fabs #导入数学模块 from time import perf_counter #导入时间模块 from numba import jit @jit d ...
- Cucumber(1) —— 环境配置
目录 学习资料 cucumber简介 cucumber环境配置 学习资料 1.cucumber官方学习网站 cucumber简介 1.cucumber是一种支持BBD(behavior-driven ...
- PHP函数:memory_get_usage
memory_get_usage() -返回分配给 PHP 的内存量 说明: memory_get_usage ([ bool $real_usage = false ] ) : int 参数: r ...
- 搭建Ubuntu虚拟机
搭建Ubuntu虚拟机 前言 1. 啰嗦一下 1.1 ubuntu虚拟机的作用 1.2 为什么选择Ubuntu 1.3 工具准备 2. 正式开始 2.1 安装VMware 2.2 创建Ubuntu虚拟 ...
- web自动化中pytest框架的使用(二)---参数化
1.pytest--参数化 在测试用例的前面加上@pytest.mark.parametrize("参数名",列表数据) 参数名:用来接收每一项数据,并作为测试用例的参数 列表数据 ...
- Ansible playbook 编程
Ansible playbook 编程详解与各种小案例 主机规划 添加用户账号 说明: 1. 运维人员使用的登录账号: 2. 所有的业务都放在 /app/ 下「yun用户的家目录」,避免业务数据乱放: ...