标签:android volley imageloader networkimageview
从前在学校用的最多的网络请求框架就是AsyncHttpClient,用久了发现这样一个问题,就是代码复用太难,基本上做不到,所以有一段时间又回归了HttpURLConnection和HttpClient,再后来又学习了OKHttp的使用,虽然这几种网络请求各有各的优势,但是原理基本上都是一样的,在android6.0中Google已经不提供HttpClient的API了,所以从长远的角度来考虑,推荐大家多用OKHttp,关于OKHttp的使用可以参见OKHttp的简单使用。除了上面说的这几种通信方式,Google在2013年(好早呀)的I/O大会上还推出了一个网络请求框架Volley,这和AsyncHttpClient的使用非常像,之前一直没有总结过Volley的使用,周末有时间总结一下,与大家分享。
Volley适用于交互频繁但是数据量小的网络请求,比如我们在上一篇博客中介绍的新闻列表,这种情况下使用Volley就是非常合适的,但是对于一些数据量大的网络请求,比如下载,Volley就显得略有力不从心。
Volley是一个开源项目,我们可以在GitHub上获得它的源代码,地址https://github.com/mcxiaoke/android-volley,拿到之后我们可以将之打包成jar包使用,也可以直接将源码拷贝到我们的项目中使用,个人推荐第二种方式,这样发生错误的时候方便我们调试,同时也有利于我们修改源码,定制我们自己的Volley。如果要拷贝源码,我们只需要将“android-volley-master\android-volley-master\src\main\java”这个文件夹下的com包拷贝到我们的项目中即可。
RequestQueue mQueue = Volley.newRequestQueue(this);获得一个请求队列只需要一个参数,就是Context,这里因为在MainActivity发起请求,所以直接用this。字符型数据的请求,我们使用StringRequest:
StringRequest sr = new StringRequest("http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.i("lenve", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } });
mQueue.add(sr);嗯,就是这么简单。那我们不禁有疑问了,刚才这个请求时get请求还是post请求?我们如何自己设置网络请求方式?我们看一下这个构造方法的源码:
/** * Creates a new GET request. * * @param url URL to fetch the string at * @param listener Listener to receive the String response * @param errorListener Error listener, or null to ignore errors */ public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(Method.GET, url, listener, errorListener); }
/** * Creates a new request with the given method. * * @param method the request {@link Method} to use * @param url URL to fetch the string at * @param listener Listener to receive the String response * @param errorListener Error listener, or null to ignore errors */ public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; }
/** * Returns a Map of parameters to be used for a POST or PUT request. Can throw * {@link AuthFailureError} as authentication may be required to provide these values. * * <p>Note that you can directly override {@link #getBody()} for custom data.</p> * * @throws AuthFailureError in the event of auth failure */ protected Map<String, String> getParams() throws AuthFailureError { return null; }看注释我们大概就明白这个方法是干什么的了,它将POST请求或者PUT请求需要的参数封装成一个Map对象,那么我们如果在POST请求中需要传参的话,直接重写这个方法就可以了,代码如下:
StringRequest sr = new StringRequest("http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.i("lenve", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }) { /** * 重写getParams(),可以自己组装post要提交的参数 */ @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> map = new HashMap<String, String>(); map.put("params1", "value1"); map.put("params1", "value1"); return map; } };好了,请求字符数据就是这么简单。
JsonObjectRequest jsonReq = new JsonObjectRequest(HTTPURL, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { JSONObject jo = response.getJSONObject("paramz"); JSONArray ja = jo.getJSONArray("feeds"); for (int i = 0; i < ja.length(); i++) { JSONObject jo1 = ja.getJSONObject(i) .getJSONObject("data"); Log.i("lenve", jo1.getString("subject")); } } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); mQueue.add(jsonReq);
ImageLoader il = new ImageLoader(mQueue, new BitmapCache()); ImageListener listener = ImageLoader.getImageListener(iv, R.drawable.ic_launcher, R.drawable.ic_launcher); il.get(IMAGEURL, listener);
public ImageContainer get(String requestUrl, ImageListener imageListener, int maxWidth, int maxHeight, ScaleType scaleType) { // only fulfill requests that were initiated from the main thread. throwIfNotOnMainThread(); final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight, scaleType); // Try to look up the request in the cache of remote images. Bitmap cachedBitmap = mCache.getBitmap(cacheKey); if (cachedBitmap != null) { // Return the cached bitmap. ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null); imageListener.onResponse(container, true); return container; } // The bitmap did not exist in the cache, fetch it! ImageContainer imageContainer = new ImageContainer(null, requestUrl, cacheKey, imageListener); // Update the caller to let them know that they should use the default bitmap. imageListener.onResponse(imageContainer, true); // Check to see if a request is already in-flight. BatchedImageRequest request = mInFlightRequests.get(cacheKey); if (request != null) { // If it is, add this request to the list of listeners. request.addContainer(imageContainer); return imageContainer; } // The request is not already in flight. Send the new request to the network and // track it. Request<Bitmap> newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, scaleType, cacheKey); mRequestQueue.add(newRequest); mInFlightRequests.put(cacheKey, new BatchedImageRequest(newRequest, imageContainer)); return imageContainer; }
<com.android.volley.toolbox.NetworkImageView android:id="@+id/iv2" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
NetworkImageView niv = (NetworkImageView) this.findViewById(R.id.iv2);
niv.setDefaultImageResId(R.drawable.ic_launcher); ImageLoader il = new ImageLoader(mQueue, new BitmapCache()); niv.setImageUrl(IMAGEURL, il);
public ImageContainer get(String requestUrl, ImageListener imageListener, int maxWidth, int maxHeight, ScaleType scaleType) { .... }没错,NetworkImageView和ImageLoader最终都会到达这个方法,所以说这两个东东其实非常像,那么在实际开发中究竟用哪个要视情况而定。
ImageRequest ir = new ImageRequest(IMAGEURL, new Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { iv3.setImageBitmap(response); } }, 200, 200, ScaleType.CENTER, Bitmap.Config.ARGB_8888, new ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); mQueue.add(ir);
public class JsonObjectRequest extends JsonRequest<JSONObject> { /** * Creates a new request. * @param method the HTTP method to use * @param url URL to fetch the JSON from * @param requestBody A {@link String} to post with the request. Null is allowed and * indicates no parameters will be posted along with request. * @param listener Listener to receive the JSON response * @param errorListener Error listener, or null to ignore errors. */ public JsonObjectRequest(int method, String url, String requestBody, Listener<JSONObject> listener, ErrorListener errorListener) { super(method, url, requestBody, listener, errorListener); } /** * Creates a new request. * @param url URL to fetch the JSON from * @param listener Listener to receive the JSON response * @param errorListener Error listener, or null to ignore errors. */ public JsonObjectRequest(String url, Listener<JSONObject> listener, ErrorListener errorListener) { super(Method.GET, url, null, listener, errorListener); } /** * Creates a new request. * @param method the HTTP method to use * @param url URL to fetch the JSON from * @param listener Listener to receive the JSON response * @param errorListener Error listener, or null to ignore errors. */ public JsonObjectRequest(int method, String url, Listener<JSONObject> listener, ErrorListener errorListener) { super(method, url, null, listener, errorListener); } /** * Creates a new request. * @param method the HTTP method to use * @param url URL to fetch the JSON from * @param jsonRequest A {@link JSONObject} to post with the request. Null is allowed and * indicates no parameters will be posted along with request. * @param listener Listener to receive the JSON response * @param errorListener Error listener, or null to ignore errors. */ public JsonObjectRequest(int method, String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener) { super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, errorListener); } /** * Constructor which defaults to <code>GET</code> if <code>jsonRequest</code> is * <code>null</code>, <code>POST</code> otherwise. * * @see #JsonObjectRequest(int, String, JSONObject, Listener, ErrorListener) */ public JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener) { this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest, listener, errorListener); } @Override protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { try { String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET)); return Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JSONException je) { return Response.error(new ParseError(je)); } } }哈,原来这么简单,光是构造方法就有五个,不过构造方法都很简单,我们就不多说,核心的功能在parseNetworkResponse方法中,这里调用成功的时候返回一个Response泛型,泛型里边的东西是一个JSONObject,其实也很简单,我们如果要处理XML,那么直接在重写parseNetworkResponse方法,在调用成功的时候直接返回一个Response泛型,这个泛型中是一个XmlPullParser对象,哈哈,很简单吧,同时,结合StringRequest的实现方式,我们实现了XMLRequest的代码:
public class XMLRequest extends Request<XmlPullParser> { private Listener<XmlPullParser> mListener; public XMLRequest(String url, Listener<XmlPullParser> mListener, ErrorListener listener) { this(Method.GET, url, mListener, listener); } public XMLRequest(int method, String url, Listener<XmlPullParser> mListener, ErrorListener listener) { super(method, url, listener); this.mListener = mListener; } @Override protected Response<XmlPullParser> parseNetworkResponse( NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); parser.setInput(new StringReader(parsed)); return Response.success(parser, HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } catch (XmlPullParserException e) { e.printStackTrace(); } return null; } @Override protected void deliverResponse(XmlPullParser response) { if (mListener != null) { mListener.onResponse(response); } } @Override protected void onFinish() { super.onFinish(); mListener = null; } }
XMLRequest xr = new XMLRequest(XMLURL, new Response.Listener<XmlPullParser>() { @Override public void onResponse(XmlPullParser parser) { try { int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_DOCUMENT: break; case XmlPullParser.START_TAG: String tagName = parser.getName(); if ("city".equals(tagName)) { Log.i("lenve", new String(parser.nextText())); } break; case XmlPullParser.END_TAG: break; } eventType = parser.next(); } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); mQueue.add(xr);
版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。
标签:android volley imageloader networkimageview
原文地址:http://blog.csdn.net/u012702547/article/details/49718955