- 本文简单的讲下如何将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 super JSONObject> mObserver;
public HttpJsonRequest(int method, String url, List 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 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);
}
}
}
这里需要注意的点,参见代码里的注释。其核心就是deliverResponse
和deliverError
两个方法的重写,其原来的方式,可以看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 super JSONObject> 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串起来了。最最关键的一步就是deliverResponse
和deliverError
.