RxAndroid + Volley 结合使用的简单例子

  • 本文简单的讲下如何将Volley的回调模式跟RxAndroid结合起来使用。使用RxAndroid的主要原因就是其能实现链式编码,代码比较好看;使用Volley的主要原因是大厂出品质量有保障,项目涉及的网络请求也比较简单。

结合使用步骤:

1.引入需要用到的资源:

compile 'com.android.volley:volley:1.0.0'
compile 'io.reactivex:rxandroid:1.2.1'

2.首先自定义自己的请求类

自定义请求类HttpJsonRequest,该类继承于com.android.volley.Request,volley
有几个自己定义好的请求类,在com.android.volley.toolbox下,根据需要使用。我这里为了跟RxAndrod结合,也为了传递传统的键值对形式参数,采用自定义的。
HttpJsonRequest.java如下:

import java.util.List;
import org.json.JSONObject;
import android.text.TextUtils;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import rx.Observer;

public class HttpJsonRequest extends Request<JSONObject> {

    private final String PROTOCOL_CHARSET = "utf-8";

    /**
     * 键值对形式参数
     */
    private List<ParamItem> mParams;

    /**
     * 观察者,在请求结束后,向其传递成功、失败的事件
     */
    private Observer<? super JSONObject> mObserver;

    public HttpJsonRequest(int method, String url, List<ParamItem> params, Observer<? super JSONObject> observer) {
        super(method, url, null);
        mObserver = observer;
        mParams = params;

        // 设置请求超时时间以及重试次数
        setRetryPolicy(new DefaultRetryPolicy(60000, 0, 1.0f));
    }

    /**
     * 该方法必须重写!!!
     * 请求完成时触发观察者中事件,记得加onCompleted();
     */
    @Override
    protected void deliverResponse(JSONObject response) {
        mObserver.onNext(response);
        mObserver.onCompleted();
    }

    /**
     * 该方法必须重写!!!
     * 发生错误时,触发事件
     */
    @Override
    public void deliverError(VolleyError error) {
        mObserver.onError(error);
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            if (TextUtils.isEmpty(jsonString)) {
                return Response.success(new JSONObject(), HttpHeaderParser.parseCacheHeaders(response));
            } else {
                return Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response));
            }
        } catch (Exception e) {
            return Response.error(new ParseError(e));
        }
    }

    /**
     * 由于参数是按照传统的键值对形式传递至后台,所以这块需要重写;
     * 如果能保证参数名称不重复,其实只要重写Request中getParams()方法即可,我这里直接重写的getBody(),因为提交图片时是同一个参数名称多次提交
     * Volley.toolbox中提供了几种强格式的request,比如com.android.volley.toolbox.JsonObjectRequest,要求参数是json格式;
     * 实际开发中,前后台交互模式很多,主要就是修改getBody()来达到自定义目的。
     */
    @Override
    public byte[] getBody() {
        String paramStr;
        if (mParams == null) {
            paramStr = "";
        } else {
            StringBuilder params = new StringBuilder();
            for (ParamItem p : mParams) {
                params.append("&").append(p.getKey()).append("=").append(p.getValue());
            }

            paramStr = params.toString();
            if (paramStr.length() > 0) {
                // 去除第一个&
                paramStr = paramStr.substring(1);
            }
        }

        try {
            return paramStr.getBytes(PROTOCOL_CHARSET);
        } catch (Exception uee) {
            throw new RuntimeException("Encoding not supported: " + PROTOCOL_CHARSET, uee);
        }
    }
}

这里需要注意的点,参见代码里的注释。其核心就是deliverResponsedeliverError两个方法的重写,其原来的方式,可以看volley.toolbox下的几个请求类源码

3.初始化请求队列以及加入请求、取消请求方法

private RequestQueue mRequestQueue;

/**
 * 获取请求队列
 */
public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
        mRequestQueue = Volley.newRequestQueue(this);
    }
    return mRequestQueue;
}

/**
 * 将一个请求加入队列,,并设置其TAG;
 * 其中tag通常就是当前请求所处的页面,页面销毁时调用cancelALl终止被页面请求
 */
public <T> void addToRequestQueue(Request<T> req, Object tag) {
    addToRequestQueue(req, tag.getClass().getSimpleName());
}

private <T> void addToRequestQueue(Request<T> req, String tag) {
    req.setTag(tag);
    BuglyLog.d(TAG, "添加请求至队列:" + req.getUrl());

    getRequestQueue().add(req);
}

/**
 * 取消指定TAG的请求,通常在onDestory()中调用
 */
public void cancelPendingRequests(Object tag) {
    cancelPendingRequests(tag.getClass().getSimpleName());
}

private void cancelPendingRequests(String tag) {
    BuglyLog.e(TAG, "从队列里去除指定TAG的请求:" + tag);
    if (mRequestQueue != null) {
        mRequestQueue.cancelAll(tag);
    }
}

这块没什么好说的,如果你要集成okhttp,就是在 Volley.newRequestQueue(this)这里做文章

4.RxAndroid与Volley结合使用

主要代码如下:

/**
 * 执行注册
 */
private void doRegister(String email, String password) {
    int versionCode = com.afap.utils.Utils.getAppVersionCode(getContext());
    String sdk = Build.VERSION.RELEASE;


    Observable.create(new Observable.OnSubscribe<JSONObject>() {
        @Override
        public void call(final Subscriber<? super JSONObject> subscriber) {
            String url = "http://www.weather.com.cn/data/cityinfo/101010100.html";
            List<ParamItem> params = new ArrayList<>();
            HttpJsonRequest request = new HttpJsonRequest(Request.Method.GET, url, null, subscriber);
            MyApplication.getInstance().addToRequestQueue(request, RegisterFormFragment.this);
        }
    })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<JSONObject>() {
                @Override
                public void onCompleted() {
                    BuglyLog.i(TAG, "Observer.onCompleted");
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    BuglyLog.e(TAG, "Observer.onError");
                }

                @Override
                public void onNext(JSONObject json) {
                    BuglyLog.i(TAG, "Observer.onNext");
                    BuglyLog.i(TAG, json.toString());
                }
            });
}

@Override
public void onDestroy() {
    MyApplication.getInstance().cancelPendingRequests(this);

    super.onDestroy();
}

以上,就已经将Volley和RxAndroid串起来了。最最关键的一步就是deliverResponsedeliverError.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容