Volley源码解析及相关拓展
来源:互联网 发布:淘宝刀具店 编辑:程序博客网 时间:2024/06/05 15:58
简述
关于Volley源码解析的文章很多,这里推荐一篇CodeKK的文章——《Volley 源码解析》
—— 注:文章链接已经找不到了,但网上转载很多。
总的来说,Volley的源码比较好理解,而且具有很强的拓展性,下面贴出两张图(流程图,类图)。建议直接看源码,然后再看这两张图,分分钟就懂了。
Volley 请求流程图
Volley 框架的主要类关系图
关于Volley的拓展
根据类图,可以发现Volley支持多种类型的请求:
- StringRequest
- JsonRequest
- JsonObjectRequest
- JsonArrayRequest
- ImageRequest
- ClearCacheRequest
1. 自定义支持Gson解析的Request
1.1 先来看一下StringRequest
public class StringRequest extends Request<String> { private Listener<String> mListener; public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(Method.GET, url, listener, errorListener); } @Override protected void deliverResponse(String response) { if (mListener != null) { mListener.onResponse(response); } } @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { // 主要是这里将网络获取的数据转成String类型 parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } // 这里只是将String类型的数据存放在Response对象的一个result字段里 return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); }}
1.2 支持Gson解析的Request
前提:数据的返回类型必须是json格式的。
public class GsonRequest extends Request<T> { private Listener<T> mListener; private final Class<T> clazz; private final Gson gson = new Gson(); // 这里要传一个实体对象进去 public StringRequest(String url, Class<T> clazz, Listener<String> listener, ErrorListener errorListener) { super(Method.GET, url, listener, errorListener); mListener = listener; this.clazz = clazz; } @Override protected void deliverResponse(T response) { if (mListener != null) { mListener.onResponse(response); } } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { // 先转成String类型的json String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); // 解析String (关键) return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } } }
2. ImageRequest中图片处理的学习
public class ImageRequest extends Request<Bitmap> { /** Socket timeout in milliseconds for image requests */ private static final int IMAGE_TIMEOUT_MS = 1000; /** Default number of retries for image requests */ private static final int IMAGE_MAX_RETRIES = 2; /** Default backoff multiplier for image requests */ private static final float IMAGE_BACKOFF_MULT = 2f; private final Response.Listener<Bitmap> mListener; private final Config mDecodeConfig; private final int mMaxWidth; private final int mMaxHeight; private ScaleType mScaleType; /** Decoding lock so that we don't decode more than one image at a time (to avoid OOM's) */ private static final Object sDecodeLock = new Object(); /** * Creates a new image request. */ public ImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight, ScaleType scaleType, Config decodeConfig, Response.ErrorListener errorListener) { super(Method.GET, url, errorListener); setRetryPolicy( new DefaultRetryPolicy(IMAGE_TIMEOUT_MS, IMAGE_MAX_RETRIES, IMAGE_BACKOFF_MULT)); mListener = listener; mDecodeConfig = decodeConfig; mMaxWidth = maxWidth; mMaxHeight = maxHeight; mScaleType = scaleType; } /** * Scales one side of a rectangle to fit aspect ratio. */ private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, int actualSecondary, ScaleType scaleType) { // If no dominant value at all, just return the actual. if ((maxPrimary == 0) && (maxSecondary == 0)) { return actualPrimary; } // If ScaleType.FIT_XY fill the whole rectangle, ignore ratio. if (scaleType == ScaleType.FIT_XY) { if (maxPrimary == 0) { return actualPrimary; } return maxPrimary; } // If primary is unspecified, scale primary to match secondary's scaling ratio. if (maxPrimary == 0) { double ratio = (double) maxSecondary / (double) actualSecondary; return (int) (actualPrimary * ratio); } if (maxSecondary == 0) { return maxPrimary; } double ratio = (double) actualSecondary / (double) actualPrimary; int resized = maxPrimary; // If ScaleType.CENTER_CROP fill the whole rectangle, preserve aspect ratio. if (scaleType == ScaleType.CENTER_CROP) { if ((resized * ratio) < maxSecondary) { resized = (int) (maxSecondary / ratio); } return resized; } if ((resized * ratio) > maxSecondary) { resized = (int) (maxSecondary / ratio); } return resized; } @Override protected Response<Bitmap> parseNetworkResponse(NetworkResponse response) { // Serialize all decode on a global lock to reduce concurrent heap usage. synchronized (sDecodeLock) { try { return doParse(response); } catch (OutOfMemoryError e) { VolleyLog.e("Caught OOM for %d byte image, url=%s", response.data.length, getUrl()); return Response.error(new ParseError(e)); } } } /** * 图片的主要处理逻辑(值得参考) * The real guts of parseNetworkResponse. Broken out for readability. */ private Response<Bitmap> doParse(NetworkResponse response) { byte[] data = response.data; BitmapFactory.Options decodeOptions = new BitmapFactory.Options(); Bitmap bitmap = null; if (mMaxWidth == 0 && mMaxHeight == 0) { decodeOptions.inPreferredConfig = mDecodeConfig; bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); } else { // If we have to resize this image, first get the natural bounds. decodeOptions.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); int actualWidth = decodeOptions.outWidth; int actualHeight = decodeOptions.outHeight; // Then compute the dimensions we would ideally like to decode to. int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight, actualWidth, actualHeight, mScaleType); int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth, actualHeight, actualWidth, mScaleType); // Decode to the nearest power of two scaling factor. decodeOptions.inJustDecodeBounds = false; // TODO(ficus): Do we need this or is it okay since API 8 doesn't support it? // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED; decodeOptions.inSampleSize = findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight); Bitmap tempBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); // If necessary, scale down to the maximal acceptable size. if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || tempBitmap.getHeight() > desiredHeight)) { bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true); tempBitmap.recycle(); } else { bitmap = tempBitmap; } } if (bitmap == null) { return Response.error(new ParseError(response)); } else { return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response)); } } @Override protected void deliverResponse(Bitmap response) { mListener.onResponse(response); } /** * 返回一个inSimpleSize的最佳值 */ static int findBestSampleSize( int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) { double wr = (double) actualWidth / desiredWidth; double hr = (double) actualHeight / desiredHeight; double ratio = Math.min(wr, hr); float n = 1.0f; while ((n * 2) <= ratio) { n *= 2; } return (int) n; }}
0 0
- Volley源码解析及相关拓展
- Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- Android Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- Volley 图片加载相关源码解析
- 【Volley】Volley源码解析
- android volley封装及源码解析
- Volley基本使用及源码解析
- Volley源码解析(一)Volley中乱码问题及解决方案
- 黑马程序员Volley 图片加载相关源码解析
- AfxGetApp()及相关拓展
- volley源码解析
- Chrome插件-postman安装图解
- scikit-learn 学习笔记
- Activity生命周期详解
- virtualbox里win7连接linux samba错误提示解决方法
- android按钮点击响应——xml方式
- Volley源码解析及相关拓展
- 段选择符和段寄存器
- 如何将class文件打包jar
- 《UNIX网络编程卷1:套接字联网API》读书笔记- 基本 TCP 套接字编程(1)
- Fragment生命周期详解
- java NIO的理解(1)
- git命令使用
- CodeForces 688B - Lovely Palindromes
- Marklogic学习 由浅入深(C)—— Marklogic的方言XQuery Dialects