当前位置: 首页 > news >正文

Android RxVolley = Volley + RxJava + OkHttp

  • Github:https://github.com/kymjs/RxVolley
  • RxVolley使用文档 V1.0:http://rxvolley.mydoc.io/

一.RxVolley使用指南

1.概述

RxVolley是一个基于Volley的网络请求库;同时支持RxJava;可以选择使用OKHttp替代默认的 HttpUrlConnection 做网络请求;可以选择使用图片加载功能(复用的网络请求将有效减少apk体积);移除了原Volley的 HttpClient 相关 API ,可在 API23 环境编译;内置了RxBus的实现,可有效替换掉EventBus等相关库;

2.依赖

使用RxVolley,需要在你的build.gradle文件中加入
compile 'com.kymjs.rxvolley:rxvolley:1.0.7'
如果你还想使用OKhttp来替代默认的HttpUrlconnection,需要加入
compile 'com.kymjs.rxvolley:okhttp:1.0.7'
如果你想使用RxVolley的图片加载功能(复用http模块可以有效减少apk大小),需要加入
compile 'com.kymjs.rxvolley:bitmapcore:1.0.7'

使用 RxVolley 做网络请求

3.简单实现

//get请求简洁版实现
RxVolley.get("http://www.kymjs.com/feed.xml", new HttpCallback() {
    @Override
    public void onSuccess(String t) {
        Loger.debug("请求到的数据:" + t);
    }
});

//post请求简洁版实现
HttpParams params = new HttpParams();
params.put("name", "kymjs");
params.put("age", 18);
params.put("image", new File("path"))//文件上传

RxVolley.post("http://kymjs.com/feed.xml", params, new HttpCallback() {
    @Override
    public void onSuccess(String t) {
        Loger.debug("请求到的数据:" + t);
    }
});

4.对Cookie等请求头的处理

//用户登录逻辑(HttpCallback中有很多重载方法,可以选择需要的实现)
HttpParams params = new HttpParams();
params.put("name", "kymjs");
params.put("age", 18);
params.put("password", "helloword");
RxVolley.post("http://kymjs.com/login", params, new HttpCallback() {
    @Override
    public void onSuccess(Map<String, String> headers, byte[] t) {
        Loger.debug("请求到的数据:" + new String(t));
        // 获取到的cookie
        Loger.debug("===" + headers.get("Set-Cookie"));
    }
});
//向服务器传递cookie信息
HttpParams params = new HttpParams();
params.put("name", "kymjs");
params.put("age", 100);

params.putHeaders("cookie", "your cookie");

RxVolley.post("http://kymjs.com/update", params, new HttpCallback() {
    @Override
    public void onSuccess(String t) {
        Loger.debug("请求到的数据:" + t);
    }
});

比起 入门 章节讲述的网络请求,你可能希望有更多的需求

5.构建网络请求

HttpParams params = new HttpParams();

//同之前的设计,传递 http 请求头可以使用 putHeaders()
params.putHeaders("cookie", "your cookie");
params.putHeaders("User-Agent", "rxvolley"); 

//传递 http 请求参数可以使用 put()
params.put("name", "kymjs");
params.put("age", "18");

//http请求的回调,内置了很多方法,详细请查看源码
//包括在异步响应的onSuccessInAsync():注不能做UI操作
//网络请求成功时的回调onSuccess()
//网络请求失败时的回调onFailure():例如无网络,服务器异常等
HttpCallback callback = new HttpCallback(){
    @Override
    public void onSuccessInAsync(byte[] t) {
    }
    @Override
    public void onSuccess(String t) {
    }
    @Override
    public void onFailure(int errorNo, String strMsg) {
    }
}

ProgressListener listener = new ProgressListener(){
    /**
     * @param transferredBytes 进度
     * @param totalSize 总量
     */
    @Override
    public void onProgress(long transferredBytes, long totalSize){
    }
}

new RxVolley.Builder()
    .url("http://www.kymjs.com/rss.xml") //接口地址  
    //请求类型,如果不加,默认为 GET 可选项: 
    //POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH  
    .httpMethod(RxVolley.Method.GET) 
    //设置缓存时间: 默认是 get 请求 5 分钟, post 请求不缓存  
    .cacheTime(6) 
    //内容参数传递形式,如果不加,默认为 FORM 表单提交,可选项 JSON 内容
    .contentType(RxVolley.ContentType.FORM)
    .params(params) //上文创建的HttpParams请求参数集
    //是否缓存,默认是 get 请求 5 缓存分钟, post 请求不缓存
    .shouldCache(true) 
    .progressListener(listener) //上传进度
    .callback(callback) //响应回调
    .encoding("UTF-8") //编码格式,默认为utf-8
    .doTask();  //执行请求操作

6.对 RxJava 的支持

RxVolley 支持返回一个 Observable 类型的数据,如下是 Result 类的原型
public class Result {
    public Map<String, String> header;
    public byte[] data;

    public Result(Map<String, String> header, byte[] data) {
        this.header = header;
        this.data = data;
    }
}

执行一次请求,并返回 Observable

Observable<Result> observable = new RxVolley.Builder()
    .url("http://www.kymjs.com/rss.xml")
    //default GET or POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH
    .httpMethod(RxVolley.Method.POST) 
    .cacheTime(6) //default: get 5min, post 0min
    .params(params)
    .contentType(RxVolley.ContentType.JSON)
    .getResult();  // 使用getResult()来返回RxJava数据类型

//当拿到 observable 对象后,你可以设置你自己的 subscriber 
observable.subscribe(subscriber);
完整的使用示例
public class MainActivity extends AppCompatActivity {

    private Subscription subscription;

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

        Observable<Result> observable = new RxVolley.Builder()
                .url("http://kymjs.com/feed.xml")
                .contentType(RxVolley.ContentType.FORM)
                .getResult();

        subscription = observable
                .map(new Func1<Result, String>() {
                    @Override
                    public String call(Result result) {
                        return new String(result.data);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String result) {
                        Log.i("kymjs", "======网络请求" + result);
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (subscription != null && subscription.isUnsubscribed()) {
            subscription.unsubscribe();
        }
    }
}

7.自定义请求

也许你是 Volley 的重度使用者(就像我),那么你一定是因为 Volley 自由的扩展性而爱上它的。 
你可以通过创建一个Request
RxVolley.Builder().setRequest(yourRequest).doTask();
去执行你的自定义 Request

一个典型自定义Request的示例:
/**
 * Form表单形式的Http请求
 */
public class FormRequest extends Request<byte[]> {

    private final HttpParams mParams;

    public FormRequest(RequestConfig config, HttpParams params, HttpCallback callback) {
        super(config, callback);
        if (params == null) {
            params = new HttpParams();
        }
        this.mParams = params;
    }

    @Override
    public String getCacheKey() {
        if (getMethod() == RxVolley.Method.POST) {
            return getUrl() + mParams.getUrlParams();
        } else {
            return getUrl();
        }
    }

    @Override
    public String getBodyContentType() {
        if (mParams.getContentType() != null) {
            return mParams.getContentType();
        } else {
            return super.getBodyContentType();
        }
    }

    @Override
    public ArrayList<HttpParamsEntry> getHeaders() {
        return mParams.getHeaders();
    }

    @Override
    public byte[] getBody() {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            mParams.writeTo(bos);
        } catch (IOException e) {
            Loger.debug("FormRequest#getBody()--->IOException writing to ByteArrayOutputStream");
        }
        return bos.toByteArray();
    }

    @Override
    public Response<byte[]> parseNetworkResponse(NetworkResponse response) {
        return Response.success(response.data, response.headers,
                HttpHeaderParser.parseCacheHeaders(getUseServerControl(), getCacheTime(),
                        response));
    }

    @Override
    protected void deliverResponse(ArrayList<HttpParamsEntry> headers, final byte[] response) {
        if (mCallback != null) {
            HashMap<String, String> map = new HashMap<>(headers.size());
            for (HttpParamsEntry entry : headers) {
                map.put(entry.k, entry.v);
            }
            mCallback.onSuccess(map, response);
        }
    }

    @Override
    public Priority getPriority() {
        return Priority.IMMEDIATE;
    }
}

8.文件(图片)下载

利用 RxVolley 的自定义请求,在库中内置了文件下载功能。你可以使用
//下载进度(可选参数,不需要可不传)
listener = new ProgressListener() {
    @Override
    public void onProgress(long transferredBytes, long totalSize) {
        Loger.debug(transferredBytes + "======" + totalSize);
    }
}

//下载回调,内置了很多方法,详细请查看源码
//包括在异步响应的onSuccessInAsync():注不能做UI操作
//下载成功时的回调onSuccess()
//下载失败时的回调onFailure():例如无网络,服务器异常等
HttpCallback callback = new HttpCallback(){
    @Override
    public void onSuccessInAsync(byte[] t) {
    }
    @Override
    public void onSuccess(String t) {
    }
    @Override
    public void onFailure(int errorNo, String strMsg) {
    }
}

RxVolley.download(FileUtils.getSDCardPath() + "/a.apk",
    "https://www.oschina.net/uploads/osc-android-app-2.4.apk",
    listener, callback);

download()原型 
既然说了下载功能是利用 RxVolley 的自定义请求创建的,不妨看看他的方法实现:

  /**
     * 下载
     *
     * @param storeFilePath    本地存储绝对路径
     * @param url              要下载的文件的url
     * @param progressListener 下载进度回调
     * @param callback         回调
     */
    public static void download(String storeFilePath, String url, ProgressListener
            progressListener, HttpCallback callback) {
        RequestConfig config = new RequestConfig();
        config.mUrl = url;
        FileRequest request = new FileRequest(storeFilePath, config, callback);
        request.setOnProgressListener(progressListener);
        new Builder().setRequest(request).doTask();
    }

9.更多可选设置

理论上来说,一切的请求设置都可以通过自定义 Request 来完成。 
但是,如果你和我一样是个懒人,当然更希望这些早就有人已经做好了。
  • 设置文件缓存的路径
默认的文件缓存路径是在SD卡根目录的 /RxVolley 文件夹下,你可以通过如下语句设置你的 cacheFolder
RxVolley.setRequestQueue(RequestQueue.newRequestQueue(cacheFolder));

需要注意的是,setRequestQueue 方法必须在 RxVolley.Build() 方法执行之前调用,也就是在使用 RxVolley 以前先设置配置信息。建议在 Application 类中完成这些设置。

  • Https设置
如果不设置,默认信任全部的https证书。可以传入自定义 SSLSocketFactory
RxVolley.setRequestQueue(RequestQueue.newRequestQueue(cacheFolder), new HttpConnectStack(null, sslSocketFactory));
需要注意的是,setRequestQueue 方法必须在 RxVolley.Build() 方法执行之前调用,也就是在使用 RxVolley 以前先设置配置信息。建议在 Application 类中完成这些设置。

一个自定义设置SSLSocketFactory的相关示例:
//下载的证书放到项目中的assets目录中
InputStream ins = context.getAssets().open("app_pay.cer"); 
CertificateFactory cerFactory = CertificateFactory
        .getInstance("X.509");
Certificate cer = cerFactory.generateCertificate(ins);
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(null, null);
keyStore.setCertificateEntry("trust", cer);

SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);

RxVolley.setRequestQueue(RequestQueue.newRequestQueue(RxVolley.CACHE_FOLDER), new HttpConnectStack(null, sslSocketFactory));
Build()中的可选设置
详细请参阅 RxVolley$Builder 类中代码。
//请求超时时间   
timeout()    

//为了更真实的模拟网络,如果读取缓存,延迟一段时间再返回缓存内容   
delayTime()   

//缓存有效时间,单位分钟  
cacheTime()  

//使用服务器控制的缓存有效期,即cookie有效期  
//(如果使用服务器端控制,则无视#cacheTime())  
useServerControl()   

//启用缓存  
shouldCache()  

//重连策略,Volley默认的重连策略是timeout=3000,重试1次  
retryPolicy()

二.Cookie持久化封装

RxVolley 默认对于 cookie 的操作是会从 HttpCallback 中返回 cookie,需要手动保存到本地。 
如果你希望框架能够自动存储 cookie,可以这么做:

按需要选择继承FormRequest或者JsonRequest (直接继承 Request 类也可以,但是复杂) 并重写
@Override
protected void deliverResponse(ArrayList<HttpParamsEntry> headers, final byte[] response) {
    if (mCallback != null) {
        HashMap<String, String> map = new HashMap<>(headers.size());
        for (HttpParamsEntry entry : headers) {
            map.put(entry.k, entry.v);
        }
        mCallback.onSuccess(map, response);
    } 
}
逻辑如上述代码,其中的map即包含了服务器返回的cookie,可以做你自己的操作了。 
最终执行你的自定义 Request
new RxVolley.Builder().setRequest(xxxxx).doTask();

在传递 Cookie 作为请求头的时候,建议写一个工具类,例如

public static HttpParams getHttpParams() {
    HttpParams params = new HttpParams();
    params.putHeader("cookie");
    return params;
}

三.使用 OkHttp

使用 OkHttp 替代HttpUrlconnection

Volley 允许你创建自己的网络请求执行器,执行器需要实现IHttpStack接口

RxVolley 的 okhttp module 已经有了使用 OkHttp 作为请求执行器的实现。

你可以使用如下代码设置,依旧需要注意的是,setRequestQueue 方法必须在 RxVolley.Build() 方法执行之前调用,也就是在使用 RxVolley 以前先设置配置信息。建议在 Application 类中完成这些设置。
RxVolley.setRequestQueue(RequestQueue.newRequestQueue(RxVolley.CACHE_FOLDER, new OkHttpStack(new OkHttpClient())));
使用 OkHttp 相关功能需要在你的 build.gradle 文件中加入
compile 'com.kymjs.rxvolley:okhttp:1.0.5'

四.Issue反馈

  • https://github.com/kymjs/RxVolley/issues

转载于:https://www.cnblogs.com/zhujiabin/p/7651983.html

相关文章:

  • 记忆化递归
  • [SDOI 2009]HH去散步
  • 关于进程内存使用的一点学习和实践
  • java中容器的学习与理解
  • 华为C8650 手机带电脑上网 / 电脑带手机上网
  • Android零基础入门第75节:Activity状态和生命周期方法
  • Android之String国际化对照表
  • 2.3 js刷新页面所有 我的程序猿之路:第十三章
  • redisCheckMem脚本
  • 搜索引擎技术之概要预览
  • 从BLOG到电子书——把wordpress备份的WXR转为epub
  • 【数据结构栈和队列】之十队列顺序存储结构
  • ORA-00980: synonym translation is no longer valid, version 9
  • [原创] css中的绝对定位和相对定位
  • 页面触底自动加载数据
  • 分享的文章《人生如棋》
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • Babel配置的不完全指南
  • express如何解决request entity too large问题
  • flask接收请求并推入栈
  • Java精华积累:初学者都应该搞懂的问题
  • MobX
  • pdf文件如何在线转换为jpg图片
  • PHP 的 SAPI 是个什么东西
  • ReactNative开发常用的三方模块
  • spring security oauth2 password授权模式
  • 爱情 北京女病人
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 巧用 TypeScript (一)
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 微信小程序设置上一页数据
  • 终端用户监控:真实用户监控还是模拟监控?
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (6)设计一个TimeMap
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (南京观海微电子)——COF介绍
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)Linux整合apache和tomcat构建Web服务器
  • (轉)JSON.stringify 语法实例讲解
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • **CI中自动类加载的用法总结
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET Core 项目指定SDK版本
  • .NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 WeakDictionary)
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET应用架构设计:原则、模式与实践 目录预览
  • @RequestMapping处理请求异常
  • @拔赤:Web前端开发十日谈
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [ 常用工具篇 ] POC-bomber 漏洞检测工具安装及使用详解