/RxHttp

OkHttp+RxJava 一条链发送请求,一行代码实现任意类中自动关闭请求,新一代Http请求神器

Primary LanguageJavaApache License 2.0Apache-2.0

Download

RxHttp

RxHttp是基于OkHttp的二次封装,并于RxJava做到无缝衔接,一条链就能发送任意请求,主要优势如下 :

1. 支持Gson、Xml、ProtoBuf、FastJson等第三方数据解析工具

2. 支持Get、Post、Put、Delete等任意请求方式,可自定义请求方式

3. 支持在Activity/Fragment/View/ViewModel/任意类中,自动关闭请求

4. 支持统一加解密,且可对单个请求设置是否加解密

5. 支持添加公共参数/头部,且可对单个请求设置是否添加公共参数/头部

6. 史上最优雅的实现文件上传/下载及进度的监听,且支持断点下载

7. 史上最优雅的对错误统一处理,且不打破Lambda表达式

8. 史上最优雅的处理多个BaseUrl及动态BaseUrl

9. 30秒即可上手,学习成本极低

上手教程

30秒上手教程:https://juejin.im/post/5cfcbbcbe51d455a694f94df

详细介绍:https://juejin.im/post/5ded221a518825125d14a1d4

自动关闭请求用到的RxLife类,详情请查看RxLife库

RxHttp&RxLife 交流群:378530627

常见问题

更新日志

Demo演示

image

更多功能,请下载Demo体验

Gradle引用方法

dependencies {
   implementation 'com.rxjava.rxhttp:rxhttp:1.3.2'
   annotationProcessor 'com.rxjava.rxhttp:rxhttp-compiler:1.3.2' //注解处理器,生成RxHttp类
   implementation 'com.rxjava.rxlife:rxlife:1.1.0'  //页面销毁,关闭请求,非必须

   //Converter 根据自己需求选择  非必须  RxHttp默认内置了GsonConverter
   implementation 'com.rxjava.rxhttp:converter-jackson:1.3.2'
   implementation 'com.rxjava.rxhttp:converter-fastjson:1.3.2'
   implementation 'com.rxjava.rxhttp:converter-protobuf:1.3.2'
   implementation 'com.rxjava.rxhttp:converter-simplexml:1.3.2'
}

注:kotlin用户,请使用kapt替代annotationProcessor

注:前方高能预警

1、API兼容

RxHttp最低要求为API 15,但是由于内部依赖OkHttp 3.14.1版本, 最低要求为API 21。 如果你要的项目要兼容到API 15,请将RxHttp内部的OkHttp剔除,并引入低版本的OkHttp,如下:

implementation('com.rxjava.rxhttp:rxhttp:x.x.x') { //xxx为RxHttp最新版本
    exclude group: "com.squareup.okhttp3"
}
implementation 'com.squareup.okhttp3:okhttp:3.12.6' //此版本最低要求 API 9

准备工作

RxHttp 要求项目使用Java 8,请在 app 的 build.gradle 添加以下代码

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

此时rebuild一下项目,就能看到RxHttp类了

配置BaseUrl

通过@DefaultDomain注解配置默认域名,@Domain注解配置非默认域名,如下:

public class Url {

    //这里使用@Domain注解后,会在RxHttp自动生成一个setDomainToUpdateIfAbsent()方法
    @Domain(name = "Update")
    public static String update = "http://update.9158.com";

    @DefaultDomain //设置为默认域名
    public static String baseUrl = "https://www.wanandroid.com/";

}

请求三部曲

RxHttp.get("/service/...")          //第一步,确定请求方式,可以选择postForm、postJson等方法
    .asString()                     //第二步,使用asXXX系列方法确定返回类型
    .subscribe(s -> {               //第三部, 订阅观察者
        //成功回调
    }, throwable -> {
        //失败回调
    });

任意请求,任意返回数据类型,皆遵循请求三部曲

任意请求,任意返回数据类型,皆遵循请求三部曲

任意请求,任意返回数据类型,皆遵循请求三部曲

get请求

RxHttp.get("/service/...")     
    .add("key", "value")
    .asString()                     
    .subscribe(s -> {               
        //成功回调
    }, throwable -> {
        //失败回调
    });

post Form请求

RxHttp.postForm("/service/...")       //发送表单形式的post请求
    .add("key", "value")
    .asString()
    .subscribe(s -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });

post Json对象请求

//发送以下Json对象                                                                   
/*                                                                             
   {                                                                           
       "name": "张三",                                                           
       "sex": 1,                                                               
       "height": 180,                                                          
       "weight": 70,                                                           
       "interest": [                                                           
           "羽毛球",                                                              
           "游泳"                                                                
       ],                                                                      
       "location": {                                                           
           "latitude": 30.7866,                                                
           "longitude": 120.6788                                               
       },                                                                      
       "address": {                                                            
           "street": "科技园路.",                                                  
           "city": "江苏苏州",                                                     
           "country": "**"                                                     
       }                                                                       
   }                                                                           
 */                                                                            
List<String> interestList = new ArrayList<>();//爱好                             
interestList.add("羽毛球");                                                       
interestList.add("游泳");                                                        
String json = "{\"height\":180,\"weight\":70}";
String address = "{\"street\":\"科技园路.\",\"city\":\"江苏苏州\",\"country\":\"**\"}";

                                                                               
RxHttp.postJson("/article/list/0/json")                                        
    .add("name", "张三")                                                         
    .add("sex", 1)                                                             
    .addAll(json) //通过addAll系列方法添加多个参数             
    .add("interest", interestList) //添加数组对象                                    
    .add("location", new Location(120.6788, 30.7866))  //添加位置对象                
    .addJsonElement("address", address) //通过字符串添加一个对象                          
    .asString()                                                                
    .subscribe(s -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });                                                                     

post Json数组请求

//发送以下Json数组                                
/*                                          
   [                                        
       {                                    
           "name": "张三"                     
       },                                   
       {                                    
           "name": "李四"                     
       },                                   
       {                                    
           "name": "王五"                     
       },                                   
       {                                    
           "name": "赵六"                     
       },                                   
       {                                    
           "name": "杨七"                     
       }                                    
   ]                                        
 */                                         
List<Name> names = new ArrayList<>();       
names.add(new Name("赵六"));                  
names.add(new Name("杨七"));   

String json = "{\"name\":\"王五\"}";

RxHttp.postJsonArray("/article/list/0/json")
    .add("name", "张三")                       
    .add(new Name("李四"))                     
    .addJsonElement(json)     
    .addAll(names)                           
    .asString()                              
    .subscribe(s -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });          
    
public class Name {

    String name;

    public Name(String name) {
        this.name = name;
    }
}

返回自定义的数据类型

RxHttp.postForm("/service/...")     //发送表单形式的post请求
    .asObject(Student.class)      //返回Student对象
    .subscribe(student -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });


RxHttp.postForm("/service/...")     //发送表单形式的post请求
    .asList(Student.class)        //返回List<Student>集合
    .subscribe(students -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });

文件上传

RxHttp.postForm("/service/...")                //发送Form表单形式的Post请求
    .addFile("file", new File("xxx/1.png"))  //添加文件
    .asString()
    .subscribe(s -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });

文件下载

RxHttp.get("/service/...")
    .asDownload("sd/xxx/1.apk") //传入本地路径
    .subscribe(s -> {
        //下载成功,回调文件下载路径
    }, throwable -> {
        //下载失败
    });

文件上传进度监听

RxHttp.postForm("/service/...")
    .add("file1", new File("xxx/1.png"))
    .asUpload(progress -> {
        //上传进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调Http执行结果
        int currentProgress = progress.getProgress(); //当前进度 0-100
        long currentSize = progress.getCurrentSize(); //当前已上传的字节大小
        long totalSize = progress.getTotalSize();     //要上传的总字节大小
    }, AndroidSchedulers.mainThread())     //指定回调(进度/成功/失败)线程,不指定,默认在请求所在线程回调
    .subscribe(s -> {             //这里s为String类型,可通过asUpload(Parser,Progress,Scheduler)方法指定返回类型
        //上传成功
    }, throwable -> {
        //上传失败
    });

文件下载进度监听

RxHttp.get("/service/...")
    .asDownload("sd/xxx/1.apk", progress -> {
        //下载进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调文件存储路径
        int currentProgress = progress.getProgress(); //当前进度 0-100
        long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
        long totalSize = progress.getTotalSize();     //要下载的总字节大小
    }, AndroidSchedulers.mainThread()) //指定回调(进度/成功/失败)线程,不指定,默认在请求所在线程回调
    .subscribe(s -> {                  //s为String类型,这里为文件存储路径
        //下载完成
    }, throwable -> {
        //下载失败
    });

断点下载、带进度回调

//断点下载,带进度
public void breakpointDownloadAndProgress() {
    String destPath = getExternalCacheDir() + "/" + "Miaobo.apk";
    long length = new File(destPath).length();
    RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")
        .setRangeHeader(length)                //设置开始下载位置,结束位置默认为文件末尾
        .asDownload(destPath, length, progress -> { //如果需要衔接上次的下载进度,则需要传入上次已下载的字节数length
            //下载进度回调,0-100,仅在进度有更新时才会回调
            int currentProgress = progress.getProgress(); //当前进度 0-100
            long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
            long totalSize = progress.getTotalSize();     //要下载的总字节大小
        }, AndroidSchedulers.mainThread()) //指定回调(进度/成功/失败)线程,不指定,默认在请求所在线程回调
        .subscribe(s -> { //s为String类型
            //下载成功,处理相关逻辑
        }, throwable -> {
            //下载失败,处理相关逻辑
        });
}

初始化

//设置debug模式,此模式下有日志打印
RxHttp.setDebug(boolean debug)
//非必须,只能初始化一次,第二次将抛出异常
RxHttp.init(OkHttpClient okHttpClient)
//或者,调试模式下会有日志输出
RxHttp.init(OkHttpClient okHttpClient, boolean debug)

添加公共参数/头部及重新设置url

//建议在Application里设置
RxHttp.setOnParamAssembly(p -> {                         
    /*根据不同请求添加不同参数,子线程执行,每次发送请求前都会被回调                    
    如果希望部分请求不回调这里,发请求前调用Param.setAssemblyEnabled(false)即可
     */                                                  
    Method method = p.getMethod();                       
    if (method.isGet()) { //Get请求                        
                                                         
    } else if (method.isPost()) { //Post请求               
                                                         
    }                                                    
    return p.add("versionName", "1.0.0")//添加公共参数         
        .addHeader("deviceType", "android"); //添加公共请求头   
});                                                      

请求开始/结束回调

RxHttp.get("/service/...")
    .asString()
    .observeOn(AndroidSchedulers.mainThread())
    .doOnSubscribe(disposable -> {
        //请求开始,当前在主线程回调
    })
    .doFinally(() -> {
        //请求结束,当前在主线程回调
    })
    .as(RxLife.as(this))  //感知生命周期
    .subscribe(pageList -> {
        //成功回调,当前在主线程回调
    }, (OnError) error -> {
        //失败回调,当前在主线程回调
    });

设置Converter

1、设置全局Converter

IConverter converter = FastJsonConverter.create();
RxHttp.setConverter(converter)

2、为请求设置单独的Converter

首先需要在任意public类中通过@Converter注解声明Converter,如下:

public class RxHttpManager {
    @Converter(name = "XmlConverter") //指定Converter名称
    public static IConverter xmlConverter = XmlConverter.create();
}

然后,rebuild 一下项目,就在自动在RxHttp类中生成setXmlConverter()方法,随后就可以调用此方法为单个请求指定Converter,如下:

RxHttp.get("/service/...")
    .setXmlConverter()   //指定使用XmlConverter,不指定,则使用全局的Converter
    .asObject(NewsDataXml.class)
    .as(RxLife.asOnMain(this))  //感知生命周期,并在主线程回调
    .subscribe(dataXml -> {
        //成功回调
    }, (OnError) error -> {
        //失败回调
    });

超时设置

1、设置全局超时

RxHttp内部默认的读、写、连接超时时间均为10s,如需修改,请自定义OkHttpClient对象,如下:

//设置读、写、连接超时时间为15s
OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(15, TimeUnit.SECONDS)
    .readTimeout(15, TimeUnit.SECONDS)
    .writeTimeout(15, TimeUnit.SECONDS)
    .build();
RxHttp.init(client);

2、为单个请求设置超时

为单个请求设置超时,使用的是RxJava的timeout(long timeout, TimeUnit timeUnit)方法,如下:

RxHttp.get("/service/...")
    .asString()
    .timeout(5, TimeUnit.SECONDS)//设置总超时时间为5s
    .as(RxLife.asOnMain(this))  //感知生命周期,并在主线程回调
    .subscribe(pageList -> {
        //成功回调
    }, (OnError) error -> {
        //失败回调
    });

注:这里设置的总超时时间要小于全局读、写、连接超时时间之和,否则无效

Activity/Fragment/View/ViewModel/任意类生命周期结束时,自动关闭请求

RxHttp.postForm("/service/...")    //发送表单形式的post请求
    .asString()
    .as(RxLife.as(this))         //生命周期结束,自动关闭请求
    .subscribe(s -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });

RxHttp.postForm("/service/...")       //发送表单形式的post请求
    .asString()
    .as(RxLife.asOnMain(this))      //在主线程回调,并在生命周期结束,自动关闭请求
    .subscribe(s -> {
        //成功回调
    }, throwable -> {
        //失败回调
    });

常用api介绍

RxHttp.postForm("/service/...") //发送Form表单形式的Post请求
    .setDomainToUpdate9158IfAbsent()      //手动设置域名,不设置会添加默认域名,此方法是通过@Domain注解生成的
    .tag("RxHttp.get")                    //为单个请求设置tag
    .setUrl("http://...")                 //重新设置url
    .setAssemblyEnabled(false)                 //设置是否添加公共参数,默认为true
    .cacheControl(CacheControl.FORCE_NETWORK)  //缓存控制
    .setParam(Param.postForm("http://..."))    //重新设置一个Param对象
    .add("key", "value")                       //添加int类型参数
    .addAll(new HashMap<>())                   //通过Map添加参数
    .addFile("file1", new File("xxx/1.png"))   //添加文件对象
    .addHeader("headerKey1", "headerValue1")   //添加头部信息
    .subscribeOn(Schedulers.io())  //指定请求线程,不指定默认在IO线程执行
    .asString()                   //使用asXXX系列方法确定返回类型,此时返回Observable对象
    .as(RxLife.asOnMain(this))    //主线程回调,并在页面销毁时,自动关闭未完成的请求
    .subscribe(s -> {    //订阅观察者
        //成功回调
    }, throwable -> {
        //失败回调
    });

混淆

RxHttp作为开源库,可混淆,也可不混淆,如果不希望被混淆,请在proguard-rules.pro文件添加以下代码

-keep class rxhttp.**{*;}

小技巧

在这教大家一个小技巧,由于使用RxHttp发送请求都遵循请求三部曲,故我们可以在android studio 设置代码模版,如下

image

如图设置好后,写代码时,输入rp,就会自动生成模版,如下:

image

RxHttp类没有自动生成,报红检查步骤

1、检查有没有依赖注解处理器 如:annotationProcessor 'com.rxjava.rxhttp:rxhttp-compiler:x.x.x’ (x.x.x为具体版本号)

2、rebuild一下项目

3、kotlin用户,要使用kapt依赖注解处理器, 如:kapt 'com.rxjava.rxhttp:rxhttp-compiler:x.x.x’ (x.x.x为具体版本号)

4、kotlin用户,检查Module的build.gradle文件中,有没有导入kapt插件 如:apply plugin: 'kotlin-kapt'

经过以上步骤后还未生成RxHttp类,请联系我。