Volley框架的理解以及自定义各个对象
2016-06-27 21:55
369 查看
Volley框架的基本流程就是:
我们在代码中RequestQueuequeue 是这样写的:
第一步:新建一个XXXrequest,参数自己定义,第一个参数是url,第二个是返回正确的处理函数,第三个是错误处理函数;XXXrequest有很多种构造函数,这只是其中的一.
第二步新建:RequestQueuequeue对象,构造函数的有两个,一个是只需要context,一个是context以及httpstack参数,第二个构造函数需要我们自己定义httpstack(这个我们后面讲)
第三步将XXXrequest加入到requestQueue中。
看起来我们什么都没有做,却能请求道我们需要的数据,这是因为volley内部已经自动完成所有的操作。接下来我就要说说volley的执行流程,RequestQueue新建出来后,就会在RequestQueue里面创建一个CacheQueue,和一个NetworkQueue,然后创建一个Thread1(CacheDIspatcher),三个Thread2(NetworkDispatcher), CacheDispatcher不断轮询RequestQueue,
把队列里面能在内存缓存中找到的资源的请求加入到CacheQueue队列中,如果内存资源不能找到,CacheDispatcher中会将请求加入到NetworkQueue网络资源队列中,这样就有了两个队列了,内存缓存的处理以后再说,先说下网络请求缓存,有队列后Thread2就会轮询NetworkQueue,将请求取出来交由Network处理,network又是有Httpstack初始化的,HttpStack又会基于当前API版本生成HttpUrlconection或者HttpClient,网络请求结束后就会调用各种回调,使用UI的handle将回调发送到主线程中,最终回到主UI线程处理视图。
从上面的XXXRequest的父类函数中根本没有看到任何Http请求的对象,那么Volley的网络 请求时怎么进行的呢?这就要去看源码了,从源码来看的话,
而在NetworkDispatcher函数中,
从NetworkDispatcher看的出来这个类需要network初始化,在调用performRequest的时候就会使用Request<T>参数,一个Network对象就会在该函数里面组装头部,body部分,然后执行请求等等;我们要注意搞清楚这个关系:
network的子类实现是BasicNetwork,
BasicNetwork的构造函数的参数有HttpStack,
HttpStack的对象里面是分为HttpUrlconnnection,HttpClient的作为请求对象的(根据当前的API水平)
而最终是由NetworkDispatcher(是个子线程)调用network.performRequest(XXXRequest<T> val),在此函数中编辑HttpStack的header和body,至于怎么调用,因为XXXRequest里面的@overwrite函数都可以得到各种参数,对于httpconnection的各种参数设置,超时时间以及是否支持缓存和缓存时间,这个是在HttpStack初始化请求对象的时候可以设置。
然后,network的子类在Volley的实现是BasicNetwork类,在构建这个对象的时候,一个HttpStack对象去传给它作为参数,而它将会调用这个HttpStack去获取事情。它是对HttpUrlConnection和HttpClient的一个包装,让外面的对象不用去关心到底是通过哪个接口来获取数据。
比如下面这个,重写Request<T>,头部改写
比如下面这个改写HttpStack:使用最新的OKHttpClient作为最底层的网络请求对象。
我们在代码中RequestQueuequeue 是这样写的:
StringRequestrequest = new StringRequest(URL, new Response.Listener<String>() { @Override public void onResponse(String s) { System.out.println("onResponse:"+s); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyErrorvolleyError) { System.out.println("onErrorResponse: " +volleyError); } }); request.setTag(toString()); RequestQueuequeue = Volley.newRequestQueue(this); queue.add(request);
第一步:新建一个XXXrequest,参数自己定义,第一个参数是url,第二个是返回正确的处理函数,第三个是错误处理函数;XXXrequest有很多种构造函数,这只是其中的一.
第二步新建:RequestQueuequeue对象,构造函数的有两个,一个是只需要context,一个是context以及httpstack参数,第二个构造函数需要我们自己定义httpstack(这个我们后面讲)
第三步将XXXrequest加入到requestQueue中。
看起来我们什么都没有做,却能请求道我们需要的数据,这是因为volley内部已经自动完成所有的操作。接下来我就要说说volley的执行流程,RequestQueue新建出来后,就会在RequestQueue里面创建一个CacheQueue,和一个NetworkQueue,然后创建一个Thread1(CacheDIspatcher),三个Thread2(NetworkDispatcher), CacheDispatcher不断轮询RequestQueue,
把队列里面能在内存缓存中找到的资源的请求加入到CacheQueue队列中,如果内存资源不能找到,CacheDispatcher中会将请求加入到NetworkQueue网络资源队列中,这样就有了两个队列了,内存缓存的处理以后再说,先说下网络请求缓存,有队列后Thread2就会轮询NetworkQueue,将请求取出来交由Network处理,network又是有Httpstack初始化的,HttpStack又会基于当前API版本生成HttpUrlconection或者HttpClient,网络请求结束后就会调用各种回调,使用UI的handle将回调发送到主线程中,最终回到主UI线程处理视图。
其中XXXrequest的需要@Overwrite函数有以下这几个 //这个函数是回调给主线程数据用的 protected void deliverResponse(T response) { this.mListener.onResponse(response); } //该函数是解析从服务器返回的数据用的,解析JSON,String,Bitmap等等,自定义XXXRequest就是改写这个函数 protected abstract Response<T> parseNetworkResponse(NetworkResponse var1); /** @deprecated 改写请求Body部分的函数*/ public String getPostBodyContentType() { return this.getBodyContentType(); } /** @deprecated */ public byte[] getPostBody() { return this.getBody(); } public String getBodyContentType() { return PROTOCOL_CONTENT_TYPE; } public byte[] getBody() {} //下面这个函数非常重要,这个函数是用来改写请求的Header部分用的。自定义XXXRequest中需要改写此函数, public byte[] getHeader() {}
从上面的XXXRequest的父类函数中根本没有看到任何Http请求的对象,那么Volley的网络 请求时怎么进行的呢?这就要去看源码了,从源码来看的话,
public interface Network { NetworkResponse performRequest(Request<?> var1) throws VolleyError; }有这样一个接口需要我们去实现。
而在NetworkDispatcher函数中,
public class NetworkDispatcher extends Thread { public NetworkDispatcher(BlockingQueue<Request<?>> queue, Network network, Cache cache, ResponseDelivery delivery) { this.mQueue = queue; this.mNetwork = network; this.mCache = cache; this.mDelivery = delivery; } public void run() { . . . Process.setThreadPriority(10); while(true) { NetworkResponse e = this.mNetwork.performRequest(request); } }
从NetworkDispatcher看的出来这个类需要network初始化,在调用performRequest的时候就会使用Request<T>参数,一个Network对象就会在该函数里面组装头部,body部分,然后执行请求等等;我们要注意搞清楚这个关系:
network的子类实现是BasicNetwork,
BasicNetwork的构造函数的参数有HttpStack,
HttpStack的对象里面是分为HttpUrlconnnection,HttpClient的作为请求对象的(根据当前的API水平)
而最终是由NetworkDispatcher(是个子线程)调用network.performRequest(XXXRequest<T> val),在此函数中编辑HttpStack的header和body,至于怎么调用,因为XXXRequest里面的@overwrite函数都可以得到各种参数,对于httpconnection的各种参数设置,超时时间以及是否支持缓存和缓存时间,这个是在HttpStack初始化请求对象的时候可以设置。
然后,network的子类在Volley的实现是BasicNetwork类,在构建这个对象的时候,一个HttpStack对象去传给它作为参数,而它将会调用这个HttpStack去获取事情。它是对HttpUrlConnection和HttpClient的一个包装,让外面的对象不用去关心到底是通过哪个接口来获取数据。
NetworkResponse performRequest(Request<?> var1) throws VolleyError;从上面的分析可以得出,有哪些有自定义的必要呢?第一XXXRequest有必要自己定义,可以定义请求的返回的类型,第二HttpStack有必要自己定义,可以定义请求对象的类型是HttpUrlconnection,还是HttpClient,还是最新最潮流的OKHttpCliet呢?自己看着办,而且也可以在这里判断是否需要缓存服务器的数据,分析header部分 和body部分。第三Cache,这个可以自己定义,在这里面,与DisCache直接关联,需不需要磁盘缓存,内存的数据多久向磁盘中缓存,也可以使用其他的缓存策略等等。第四自定义RequestQueues,在这里重写各个处理线程的个数。
比如下面这个,重写Request<T>,头部改写
RequestQueue queue = Volley.newRequestQueue(this); String url = "http://www.somewebsite.com"; StringRequest postRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // response Log.d("Response", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // TODO Auto-generated method stub Log.d("ERROR","error => "+error.toString()); } } ) { @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> params = new HashMap<String, String>(); params.put("User-Agent", "Nintendo Gameboy"); params.put("Accept-Language", "fr"); return params; } }; queue.add(postRequest);
比如下面这个改写HttpStack:使用最新的OKHttpClient作为最底层的网络请求对象。
/**集成最新OKHttpClient; * An {@link com.android.volley.toolbox.HttpStack HttpStack} implementation which * uses OkHttp as its transport. */ public class OkHttpStack extends HurlStack { private final OkHttpClient client; public OkHttpStack() { this(new OkHttpClient()); } public OkHttpStack(OkHttpClient client) { if (client == null) { throw new NullPointerException("Client must not be null."); } this.client = client; } @Override protected HttpURLConnection createConnection(URL url) throws IOException { return client.open(url); } } public class OkHttpStack implements HttpStack { private final OkHttpClient mClient; public OkHttpStack(OkHttpClient client) { this.mClient = client; } @Override public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError { OkHttpClient client = mClient.clone(); int timeoutMs = request.getTimeoutMs(); client.setConnectTimeout(timeoutMs, TimeUnit.MILLISECONDS); client.setReadTimeout(timeoutMs, TimeUnit.MILLISECONDS); client.setWriteTimeout(timeoutMs, TimeUnit.MILLISECONDS); com.squareup.okhttp.Request.Builder okHttpRequestBuilder = new com.squareup.okhttp.Request.Builder(); okHttpRequestBuilder.url(request.getUrl()); Map<String, String> headers = request.getHeaders(); for (final String name : headers.keySet()) { okHttpRequestBuilder.addHeader(name, headers.get(name)); } for (final String name : additionalHeaders.keySet()) { okHttpRequestBuilder.addHeader(name, additionalHeaders.get(name)); } setConnectionParametersForRequest(okHttpRequestBuilder, request); com.squareup.okhttp.Request okHttpRequest = okHttpRequestBuilder.build(); Call okHttpCall = client.newCall(okHttpRequest); Response okHttpResponse = okHttpCall.execute(); StatusLine responseStatus = new BasicStatusLine ( parseProtocol(okHttpResponse.protocol()), okHttpResponse.code(), okHttpResponse.message() ); BasicHttpResponse response = new BasicHttpResponse(responseStatus); response.setEntity(entityFromOkHttpResponse(okHttpResponse)); Headers responseHeaders = okHttpResponse.headers(); for (int i = 0, len = responseHeaders.size(); i < len; i++) { final String name = responseHeaders.name(i), value = responseHeaders.value(i); if (name != null) { response.addHeader(new BasicHeader(name, value)); } } return response; } private static HttpEntity entityFromOkHttpResponse(Response r) throws IOException { BasicHttpEntity entity = new BasicHttpEntity(); ResponseBody body = r.body(); entity.setContent(body.byteStream()); entity.setContentLength(body.contentLength()); entity.setContentEncoding(r.header("Content-Encoding")); if (body.contentType() != null) { entity.setContentType(body.contentType().type()); } return entity; } @SuppressWarnings("deprecation") private static void setConnectionParametersForRequest (com.squareup.okhttp.Request.Builder builder, Request<?> request) throws IOException, AuthFailureError { switch (request.getMethod()) { case Request.Method.DEPRECATED_GET_OR_POST: // Ensure backwards compatibility. // Volley assumes a request with a null body is a GET. byte[] postBody = request.getPostBody(); if (postBody != null) { builder.post(RequestBody.create (MediaType.parse(request.getPostBodyContentType()), postBody)); } break; case Request.Method.GET: builder.get(); break; case Request.Method.DELETE: builder.delete(); break; case Request.Method.POST: builder.post(createRequestBody(request)); break; case Request.Method.PUT: builder.put(createRequestBody(request)); break; case Request.Method.HEAD: builder.head(); break; case Request.Method.OPTIONS: builder.method("OPTIONS", null); break; case Request.Method.TRACE: builder.method("TRACE", null); break; case Request.Method.PATCH: builder.patch(createRequestBody(request)); break; default: throw new IllegalStateException("Unknown method type."); } } private static ProtocolVersion parseProtocol(final Protocol p) { switch (p) { case HTTP_1_0: return new ProtocolVersion("HTTP", 1, 0); case HTTP_1_1: return new ProtocolVersion("HTTP", 1, 1); case SPDY_3: return new ProtocolVersion("SPDY", 3, 1); case HTTP_2: return new ProtocolVersion("HTTP", 2, 0); } throw new IllegalAccessError("Unkwown protocol"); } private static RequestBody createRequestBody(Request r) throws AuthFailureError { final byte[] body = r.getBody(); if (body == null) return null; return RequestBody.create(MediaType.parse(r.getBodyContentType()), body); } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories