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 {

    private final String PROTOCOL_CHARSET = "utf-8";

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

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

    public HttpJsonRequest(int method, String url, List params, Observer 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 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  void addToRequestQueue(Request req, Object tag) {
    addToRequestQueue(req, tag.getClass().getSimpleName());
}

private  void addToRequestQueue(Request 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() {
        @Override
        public void call(final Subscriber subscriber) {
            String url = "http://www.weather.com.cn/data/cityinfo/101010100.html";
            List 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() {
                @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.

你可能感兴趣的:(RxAndroid + Volley 结合使用的简单例子)