尊重原创 http://write.blog.csdn.net/postedit/26002961

通过前面浅析(一)浅析(二)的分析。相信大家对于Volley有了初步的认识,可是假设想更深入的理解。还须要靠大家多多看源代码。

这篇文章中我们主要来研究一下使用Volley框架请求大量图片的原理,在Android的应用中,通过http请求获取的数据主要有三类:

1、json 

2、xml

3、Image

当中json和xml的获取事实上原理非常easy。使用Volley获取感觉有点大財小用了,了解Volley获取图片的原理才是比較有意义的。由于里面涉及到非常多知识点,比方获取大量图片怎样防止OOM。

那么我们就開始研究源代码吧。

(1) ImageLoader.java

通过它的名字我们就知道是用来载入Image的工具类

  1. /**
  2. 通过调用ImageLoader的get方法就能够获取到图片,然后通过一个Listener回调,将图片设置到ImgeView中(这种方法务必在主线程中调用)
  3. */
  4. public class ImageLoader {
  5. /** 前面已经接触过。请求队列(事实上不是真实的队列,里面包括了本地队列和网络队列) */
  6. private final RequestQueue mRequestQueue;
  7.  
  8. /** 图片缓冲,这个缓存不是前面提到的磁盘缓存,这个是内存缓存。我们能够通过LruCache实现这个接口 */
  9. private final ImageCache mCache;
  10.  
  11. /**
  12. * 用于存放具有同样cacheKey的请求
  13. */
  14. private final HashMap<String, BatchedImageRequest> mInFlightRequests =
  15. new HashMap<String, BatchedImageRequest>();
  16.  
  17. /** 用于存放具有同样Key,而且返回了数据的请求*/
  18. private final HashMap<String, BatchedImageRequest> mBatchedResponses =
  19. new HashMap<String, BatchedImageRequest>();
  20.  
  21. /** Handler to the main thread. */
  22. private final Handler mHandler = new Handler(Looper.getMainLooper());
  23.  
  24. /** Runnable for in-flight response delivery. */
  25. private Runnable mRunnable;
  26.  
  27. /**
  28. * Simple cache adapter interface. If provided to the ImageLoader, it
  29. * will be used as an L1 cache before dispatch to Volley. Implementations
  30. * must not block. Implementation with an LruCache is recommended.
  31. */
  32. public interface ImageCache {
  33. public Bitmap getBitmap(String url);
  34. public void putBitmap(String url, Bitmap bitmap);
  35. }
  36.  
  37. /**
  38. * 构造函数须要传入一个RequestQueue对象和一个内存缓存对象
  39. * @param queue The RequestQueue to use for making image requests.
  40. * @param imageCache The cache to use as an L1 cache.
  41. */
  42. public ImageLoader(RequestQueue queue, ImageCache imageCache) {
  43. mRequestQueue = queue;
  44. mCache = imageCache;
  45. }
  46.  
  47. /**
  48. * 用于图片获取成功或者失败的回调
  49. * @param imageView 须要设置图片的ImageView.
  50. * @param defaultImageResId 默认显示图片.
  51. * @param errorImageResId 出错时显示的图片.
  52. */
  53. public static ImageListener getImageListener(final ImageView view,
  54. final int defaultImageResId, final int errorImageResId) {
  55. return new ImageListener() {
  56. @Override
  57. public void onErrorResponse(VolleyError error) {
  58. //出错而且设置了出错图片。那么显示出错图片
  59. if (errorImageResId != 0) {
  60. view.setImageResource(errorImageResId);
  61. }
  62. }
  63.  
  64. @Override
  65. public void onResponse(ImageContainer response, boolean isImmediate) {
  66. if (response.getBitmap() != null) {
  67. //成功获取到了数据,则显示
  68. view.setImageBitmap(response.getBitmap());
  69. } else if (defaultImageResId != 0) {
  70. //数据为空,那么显示默认图片
  71. view.setImageResource(defaultImageResId);
  72. }
  73. }
  74. };
  75. }
  76.  
  77. /**
  78. * 推断图片是否已经缓存,不同尺寸的图片的cacheKey是不一样的
  79. * @param requestUrl 图片的url
  80. * @param maxWidth 请求图片的宽度.
  81. * @param maxHeight 请求图片的高度.
  82. * @return 返回true则缓存.
  83. */
  84. public boolean isCached(String requestUrl, int maxWidth, int maxHeight) {
  85. throwIfNotOnMainThread();
  86.  
  87. String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);
  88. return mCache.getBitmap(cacheKey) != null;
  89. }
  90.  
  91. /**
  92. * 这种方法时个核心方法。我们主要通过它来获取图片
  93. *
  94. * @param requestUrl The URL of the image to be loaded.
  95. * @param defaultImage Optional default image to return until the actual image is loaded.
  96. */
  97. public ImageContainer get(String requestUrl, final ImageListener listener) {
  98. return get(requestUrl, listener, 0, 0);
  99. }
  100.  
  101. /**
  102. * 这种方法比上面方法多了两个參数,假设传入则图片大小会做相应处理。假设不传默觉得0,图片大小不做处理
  103. * @param requestUrl The url of the remote image
  104. * @param imageListener The listener to call when the remote image is loaded
  105. * @param maxWidth The maximum width of the returned image.
  106. * @param maxHeight The maximum height of the returned image.
  107. * @return A container object that contains all of the properties of the request, as well as
  108. * the currently available image (default if remote is not loaded).
  109. */
  110. public ImageContainer get(String requestUrl, ImageListener imageListener,
  111. int maxWidth, int maxHeight) {
  112. // only fulfill requests that were initiated from the main thread.
  113. throwIfNotOnMainThread();
  114. //获取key,事实上就是url,width,height依照某种格式拼接
  115. final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);
  116.  
  117. // 首先从缓存里面取图片
  118. Bitmap cachedBitmap = mCache.getBitmap(cacheKey);
  119. if (cachedBitmap != null) {
  120. // 假设缓存命中,则直接放回
  121. ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null);
  122. imageListener.onResponse(container, true);
  123. return container;
  124. }
  125.  
  126. // 没有命中。则创建一个ImageContainer,注意此时图片数据传入的null,
  127. ImageContainer imageContainer =
  128. new ImageContainer(null, requestUrl, cacheKey, imageListener);
  129.  
  130. // 这就是为什么在onResponse中我们须要推断图片数据是否为空,此时就是为空的
  131. imageListener.onResponse(imageContainer, true);
  132.  
  133. // 推断同一个key的请求是否已经存在
  134. BatchedImageRequest request = mInFlightRequests.get(cacheKey);
  135. if (request != null) {
  136. // 假设存在,则直接增加request中,没有必要对一个key发送多个请求
  137. request.addContainer(imageContainer);
  138. return imageContainer;
  139. }
  140.  
  141. // 发送一个请求,并增加RequestQueue
  142. Request<?> newRequest =
  143. new ImageRequest(requestUrl, new Listener<Bitmap>() {
  144. @Override
  145. public void onResponse(Bitmap response) {
  146. //成功获取到图片
  147. onGetImageSuccess(cacheKey, response);
  148. }
  149. }, maxWidth, maxHeight,
  150. Config.RGB_565, new ErrorListener() {
  151. @Override
  152. public void onErrorResponse(VolleyError error) {
  153. onGetImageError(cacheKey, error);
  154. }
  155. });
  156. mRequestQueue.add(newRequest);
  157. VolleyLog.e("-------------->"+newRequest.getSequence());
  158. //增加到HashMap中,表明这个key已经存在一个请求
  159. mInFlightRequests.put(cacheKey,
  160. new BatchedImageRequest(newRequest, imageContainer));
  161. return imageContainer;
  162. }
  163.  
  164. /**
  165. * Handler for when an image was successfully loaded.
  166. * @param cacheKey The cache key that is associated with the image request.
  167. * @param response The bitmap that was returned from the network.
  168. */
  169. private void onGetImageSuccess(String cacheKey, Bitmap response) {
  170. // 获取图片成功。放入缓存
  171. mCache.putBitmap(cacheKey, response);
  172.  
  173. // 将cacheKey相应的请求从mInFlightRequests中移除
  174. BatchedImageRequest request = mInFlightRequests.remove(cacheKey);
  175.  
  176. if (request != null) {
  177. // Update the response bitmap.
  178. request.mResponseBitmap = response;
  179.  
  180. // Send the batched response
  181. batchResponse(cacheKey, request);
  182. }
  183. }
  184.  
  185. /**
  186. * Handler for when an image failed to load.
  187. * @param cacheKey The cache key that is associated with the image request.
  188. */
  189. private void onGetImageError(String cacheKey, VolleyError error) {
  190. // Notify the requesters that something failed via a null result.
  191. // Remove this request from the list of in-flight requests.
  192. BatchedImageRequest request = mInFlightRequests.remove(cacheKey);
  193.  
  194. if (request != null) {
  195. // Set the error for this request
  196. request.setError(error);
  197.  
  198. // Send the batched response
  199. batchResponse(cacheKey, request);
  200. }
  201. }
  202.  
  203. /**
  204. * Container object for all of the data surrounding an image request.
  205. */
  206. public class ImageContainer {
  207. /**
  208. * 保存从网络获取的图片
  209. */
  210. private Bitmap mBitmap;
  211.  
  212. private final ImageListener mListener;
  213.  
  214. /** The cache key that was associated with the request */
  215. private final String mCacheKey;
  216.  
  217. /** The request URL that was specified */
  218. private final String mRequestUrl;
  219.  
  220. /**
  221. * Constructs a BitmapContainer object.
  222. * @param bitmap The final bitmap (if it exists).
  223. * @param requestUrl The requested URL for this container.
  224. * @param cacheKey The cache key that identifies the requested URL for this container.
  225. */
  226. public ImageContainer(Bitmap bitmap, String requestUrl,
  227. String cacheKey, ImageListener listener) {
  228. mBitmap = bitmap;
  229. mRequestUrl = requestUrl;
  230. mCacheKey = cacheKey;
  231. mListener = listener;
  232. }
  233.  
  234. /**
  235. * 取消一个图片请求
  236. */
  237. public void cancelRequest() {
  238. if (mListener == null) {
  239. return;
  240. }
  241. //推断此key相应的请求有没有
  242. BatchedImageRequest request = mInFlightRequests.get(mCacheKey);
  243. if (request != null) {
  244. /**假设存在,request中mContainers中的这个Container,假设mContainers的size为0,那么
  245. removeContainerAndCancelIfNecessary返回true
  246. */
  247. boolean canceled = request.removeContainerAndCancelIfNecessary(this);
  248. if (canceled) {
  249. //假设返回true,那么说明没有不论什么一个ImageView对这个请求感兴趣,须要移除它
  250. mInFlightRequests.remove(mCacheKey);
  251. }
  252. } else {
  253. // 推断是否这个request已经成功返回了
  254. request = mBatchedResponses.get(mCacheKey);
  255. if (request != null) {
  256. request.removeContainerAndCancelIfNecessary(this);
  257. if (request.mContainers.size() == 0) {
  258. //假设已经成功返回,而且没有ImageView对他感兴趣。那么删除它
  259. mBatchedResponses.remove(mCacheKey);
  260. }
  261. }
  262. }
  263. }
  264.  
  265. /**
  266. * Returns the bitmap associated with the request URL if it has been loaded, null otherwise.
  267. */
  268. public Bitmap getBitmap() {
  269. return mBitmap;
  270. }
  271.  
  272. /**
  273. * Returns the requested URL for this container.
  274. */
  275. public String getRequestUrl() {
  276. return mRequestUrl;
  277. }
  278. }
  279.  
  280. /**
  281. * 对Request的一个包装。将全部有共同key的请求放入一个LinkedList中
  282. */
  283. private class BatchedImageRequest {
  284. /** The request being tracked */
  285. private final Request<?
  286.  
  287. > mRequest;
  288.  
  289. /** The result of the request being tracked by this item */
  290. private Bitmap mResponseBitmap;
  291.  
  292. /** Error if one occurred for this response */
  293. private VolleyError mError;
  294.  
  295. /** 存放具有共同key的ImageContainer*/
  296. private final LinkedList<ImageContainer> mContainers = new LinkedList<ImageContainer>();
  297.  
  298. /**
  299. * Constructs a new BatchedImageRequest object
  300. * @param request The request being tracked
  301. * @param container The ImageContainer of the person who initiated the request.
  302. */
  303. public BatchedImageRequest(Request<?
  304.  
  305. > request, ImageContainer container) {
  306. mRequest = request;
  307. mContainers.add(container);
  308. }
  309.  
  310. /**
  311. * Set the error for this response
  312. */
  313. public void setError(VolleyError error) {
  314. mError = error;
  315. }
  316.  
  317. /**
  318. * Get the error for this response
  319. */
  320. public VolleyError getError() {
  321. return mError;
  322. }
  323.  
  324. /**
  325. * Adds another ImageContainer to the list of those interested in the results of
  326. * the request.
  327. */
  328. public void addContainer(ImageContainer container) {
  329. mContainers.add(container);
  330. }
  331.  
  332. /**
  333. * 移除一个ImageContainer。假设此时size==0,那么须要从mInFlightRequests中移除该BatchedImageRequest
  334. * @param container The container to remove from the list
  335. * @return True if the request was canceled, false otherwise.
  336. */
  337. public boolean removeContainerAndCancelIfNecessary(ImageContainer container) {
  338. mContainers.remove(container);
  339. if (mContainers.size() == 0) {
  340. mRequest.cancel();
  341. return true;
  342. }
  343. return false;
  344. }
  345. }
  346.  
  347. /**
  348. * 当请求返回后。将BatchedImageRequest放入到mBatchedResponses,然后将结果发送给全部具有同样key的ImageContainer,ImageContainer通过里面的Listener发送到ImageView,从而显示出来
  349. * @param cacheKey The cacheKey of the response being delivered.
  350. * @param request The BatchedImageRequest to be delivered.
  351. * @param error The volley error associated with the request (if applicable).
  352. */
  353. private void batchResponse(String cacheKey, BatchedImageRequest request) {
  354. mBatchedResponses.put(cacheKey, request);
  355. // If we don't already have a batch delivery runnable in flight, make a new one.
  356. // Note that this will be used to deliver responses to all callers in mBatchedResponses.
  357. if (mRunnable == null) {
  358. mRunnable = new Runnable() {
  359. @Override
  360. public void run() {
  361. for (BatchedImageRequest bir : mBatchedResponses.values()) {
  362. for (ImageContainer container : bir.mContainers) {
  363. // If one of the callers in the batched request canceled the request
  364. // after the response was received but before it was delivered,
  365. // skip them.
  366. if (container.mListener == null) {
  367. continue;
  368. }
  369. if (bir.getError() == null) {
  370. container.mBitmap = bir.mResponseBitmap;
  371. container.mListener.onResponse(container, false);
  372. } else {
  373. container.mListener.onErrorResponse(bir.getError());
  374. }
  375. }
  376. }
  377. mBatchedResponses.clear();
  378. mRunnable = null;
  379. }
  380.  
  381. };
  382. // Post the runnable.
  383. mHandler.postDelayed(mRunnable, mBatchResponseDelayMs);
  384. }
  385. }
  386.  
  387. /**
  388. * 获取一个请求的key,拼接规则就是使用#讲几个连接起来
  389. * @param url The URL of the request.
  390. * @param maxWidth The max-width of the output.
  391. * @param maxHeight The max-height of the output.
  392. */
  393. private static String getCacheKey(String url, int maxWidth, int maxHeight) {
  394. return new StringBuilder(url.length() + 12).append("#W").append(maxWidth)
  395. .append("#H").append(maxHeight).append(url).toString();
  396. }
  397.  
  398. }

ImageLoader的代码还是比較复杂的。可是思路还是比較清晰的,总结例如以下:

1、通过ImageLoader的get方法获取图片,假设我们仅仅想获取原始图片。不用关心大小,则仅仅用传入url和Listener,假设须要设置图片大小,那么传入你须要设置大大小

2、get方法中。先回去缓存中查找,假设命中。那么就直接放回,假设没有命中,那么就推断mInFlightRequests中是否有同样key的BatchedImageRequest,假设有则直接将ImageConainer增加BatchedImageRequest的mContainres中,由于对于同一个key没有必要发送两次请求

3、假设在mInFlightRequest中没有此key,那么须要创建一个ImageRequest对象,并增加RequestQueue中,并使用ImageRequest创建一个BatchedImageRequest增加mInFlightRequest

4、当请求返回后,将BatchedImageRequest从mInFlightRequest中移除,增加mBatchedResponses中,将返回结果返回给全部的ImageContainer

5、假设一个ImageContainer在收到返回结果之前就被cancel掉。那么须要将它从mInFlightRequest的mContainers中移除,假设移除后mContainers的size为0。说明这个请求仅仅有一次,取消了就没有必要请求,须要把BatchedImageRequestmInFlightRequest中移走,从假设不等于0,说明这个请求被其它的ImageContainr须要,不能取消

假设我们不过获取少量图片,Volley框架为我们提供了一个NetworkImageView,这个类继承自ImageView,使用时,我们只须要调用setImageUrl就可以,以下就来看事实上现机制

(2) NetworkImageView.java

  1. public class NetworkImageView extends ImageView {
  2. /** 须要载入图片的url */
  3. private String mUrl;
  4.  
  5. /**
  6. * 默认显示图片的id
  7. */
  8. private int mDefaultImageId;
  9.  
  10. /**
  11. * 错误图片的id
  12. */
  13. private int mErrorImageId;
  14.  
  15. /** ImageLoader对象,事实上就是用该对象去获取图片。所以了解了ImageLoader后。这个类非常好理解 */
  16. private ImageLoader mImageLoader;
  17.  
  18. /**把这个对象当成url和Listener的封装就可以 */
  19. private ImageContainer mImageContainer;
  20.  
  21. public NetworkImageView(Context context) {
  22. this(context, null);
  23. }
  24.  
  25. public NetworkImageView(Context context, AttributeSet attrs) {
  26. this(context, attrs, 0);
  27. }
  28.  
  29. public NetworkImageView(Context context, AttributeSet attrs, int defStyle) {
  30. super(context, attrs, defStyle);
  31. }
  32.  
  33. /**
  34. * 设置Url
  35. *
  36. * @param url The URL that should be loaded into this ImageView.
  37. * @param imageLoader ImageLoader that will be used to make the request.
  38. */
  39. public void setImageUrl(String url, ImageLoader imageLoader) {
  40. mUrl = url;
  41. mImageLoader = imageLoader;
  42. // 这种方法我们后面分析
  43. loadImageIfNecessary(false);
  44. }
  45.  
  46. /**
  47. * Sets the default image resource ID to be used for this view until the attempt to load it
  48. * completes.
  49. */
  50. public void setDefaultImageResId(int defaultImage) {
  51. mDefaultImageId = defaultImage;
  52. }
  53.  
  54. /**
  55. * Sets the error image resource ID to be used for this view in the event that the image
  56. * requested fails to load.
  57. */
  58. public void setErrorImageResId(int errorImage) {
  59. mErrorImageId = errorImage;
  60. }
  61.  
  62. /**
  63. * 这种方法在onLayout方法中传入true,其它地方传入false
  64. * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
  65. */
  66. void loadImageIfNecessary(final boolean isInLayoutPass) {
  67. int width = getWidth();
  68. int height = getHeight();
  69.  
  70. boolean wrapWidth = false, wrapHeight = false;
  71. if (getLayoutParams() != null) {
  72. wrapWidth = getLayoutParams().width == LayoutParams.WRAP_CONTENT;
  73. wrapHeight = getLayoutParams().height == LayoutParams.WRAP_CONTENT;
  74. }
  75.  
  76. // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content
  77. // view, hold off on loading the image.
  78. boolean isFullyWrapContent = wrapWidth && wrapHeight;
  79. if (width == 0 && height == 0 && !isFullyWrapContent) {
  80. return;
  81. }
  82.  
  83. // if the URL to be loaded in this view is empty, cancel any old requests and clear the
  84. // currently loaded image.
  85. if (TextUtils.isEmpty(mUrl)) {
  86. if (mImageContainer != null) {
  87. mImageContainer.cancelRequest();
  88. mImageContainer = null;
  89. }
  90. setDefaultImageOrNull();
  91. return;
  92. }
  93.  
  94. // if there was an old request in this view, check if it needs to be canceled.
  95. if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
  96. if (mImageContainer.getRequestUrl().equals(mUrl)) {
  97. //假设请求url同样,则直接return
  98. return;
  99. } else {
  100. // 请求url不同。则cancel,并显示默认图片或者不显示图片
  101. mImageContainer.cancelRequest();
  102. setDefaultImageOrNull();
  103. }
  104. }
  105.  
  106. // Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens.
  107. int maxWidth = wrapWidth ?
  108.  
  109. 0 : width;
  110. int maxHeight = wrapHeight ?
  111.  
  112. 0 : height;
  113.  
  114. //调用了get方法
  115. ImageContainer newContainer = mImageLoader.get(mUrl,
  116. new ImageListener() {
  117. @Override
  118. public void onErrorResponse(VolleyError error) {
  119. if (mErrorImageId != 0) {
  120. setImageResource(mErrorImageId);
  121. }
  122. }
  123.  
  124. @Override
  125. public void onResponse(final ImageContainer response, boolean isImmediate) {
  126. // If this was an immediate response that was delivered inside of a layout
  127. // pass do not set the image immediately as it will trigger a requestLayout
  128. // inside of a layout. Instead, defer setting the image by posting back to
  129. // the main thread.
  130. if (isImmediate && isInLayoutPass) {
  131. post(new Runnable() {
  132. @Override
  133. public void run() {
  134. onResponse(response, false);
  135. }
  136. });
  137. return;
  138. }
  139.  
  140. if (response.getBitmap() != null) {
  141. setImageBitmap(response.getBitmap());
  142. } else if (mDefaultImageId != 0) {
  143. setImageResource(mDefaultImageId);
  144. }
  145. }
  146. }, maxWidth, maxHeight);
  147.  
  148. // update the ImageContainer to be the new bitmap container.
  149. mImageContainer = newContainer;
  150. }
  151.  
  152. private void setDefaultImageOrNull() {
  153. if(mDefaultImageId != 0) {
  154. setImageResource(mDefaultImageId);
  155. }
  156. else {
  157. setImageBitmap(null);
  158. }
  159. }
  160.  
  161. @Override
  162. protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  163. super.onLayout(changed, left, top, right, bottom);
  164. loadImageIfNecessary(true);
  165. }
  166.  
  167. @Override
  168. protected void onDetachedFromWindow() {
  169. if (mImageContainer != null) {
  170. // If the view was bound to an image request, cancel it and clear
  171. // out the image from the view.
  172. mImageContainer.cancelRequest();
  173. setImageBitmap(null);
  174. // also clear out the container so we can reload the image if necessary.
  175. mImageContainer = null;
  176. }
  177. super.onDetachedFromWindow();
  178. }
  179.  
  180. @Override
  181. protected void drawableStateChanged() {
  182. super.drawableStateChanged();
  183. invalidate();
  184. }
  185. }

到眼下为止Volley框架的源代码分析差点儿相同了。下一篇文章我打算使用一个GridView展示大量图片的样例来解说Volley的使用.....

Android网络通信Volley框架源代码浅析(三)的更多相关文章

  1. Android网络通信Volley框架源代码浅析(一)

    尊重原创http://blog.csdn.net/yuanzeyao/article/details/25837897 从今天開始,我打算为大家呈现关于Volley框架的源代码分析的文章,Volley ...

  2. Android网络通信Volley框架源代码浅析(二)

    尊重原创 http://write.blog.csdn.net/postedit/25921795 在前面的一片文章Volley框架浅析(一)中我们知道在RequestQueue这个类中,有两个队列: ...

  3. Volley框架源代码分析

    Volley框架分析Github链接 Volley框架分析 Volley源代码解析 为了学习Volley的网络框架,我在AS中将Volley代码又一次撸了一遍,感觉这样的照抄代码也是一种挺好的学习方式 ...

  4. Android 网络通信框架Volley简介(Google IO 2013)

    1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient( ...

  5. Android 网络通信框架Volley(一)

    转自:http://blog.csdn.net/t12x3456/article/details/9221611 1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫 ...

  6. [转]Android 网络通信框架Volley简介(Google IO 2013)

    Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v= ...

  7. 【转】Android 网络通信框架Volley简介(Google IO 2013)

    Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v= ...

  8. Android 网络通信框架Volley简介

    1.1. Volley引入的背景在以前,我们可能面临如下很多麻烦的问题. 比如以前从网上下载图片的步骤可能是这样的流程: 在ListAdapter#getView()里开始图像的读取. 通过Async ...

  9. Android 网络通信框架Volley基本介绍

    Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v= ...

随机推荐

  1. poj3126解题报告

    题意:简单的说就是:有一个人门牌号是一个四位数的整数,并且还是一个素数,现在他想要换成另外一个四位数且是素数的门牌号,而且,每次都只能更换这个四位数的一个位置的数 ,也就是每换一次都只改变一个数字,而 ...

  2. hdu 1698 Just a Hook(线段树之 成段更新)

    Just a Hook                                                                             Time Limit: ...

  3. 在自己的base脚本中实现自动补全

    在90年代Linux和DOS共存的年代里,Linux的Shell们有一个最微不足道但也最实用的小功能,就是命令自动补全.而DOS那个笨蛋一直到死都没学会什么叫易用. Linux的这个微不足道的小传统一 ...

  4. Oracle基本流程语句

    ====1.IF语句==========

  5. String,StringBuffer以及StringBuilder的差别

    1.定义: String:String 类代表字符串. Java 程序中的全部字符串字面值(如"abc" )都作为此类的实例实现. 字符串是常量:它们的值在创建之后不能更改. 字符 ...

  6. android4.0 USB Camera示例(五个辅助)jpg压缩

    前的最后一个 我们说,一个直接yuv变成jpg该功能 但是转换不成功 主要功能是yuv420转jpg的 根据研究发现 yuv420的序列是这种 YYYY YYYY UVUV 而yuv422的隔行扫描的 ...

  7. session校验是否登录

    由于一个网站要有好多页面,如果每个页面都写上检验session是否为空,太麻烦了,所以写个工具类,就方便了. 1首先创建一个类库Common 2,然后在这个类库添加引用 3在Common继承 :Sys ...

  8. CSS 初探

    Css: 指层叠样式表 (Cascading Style Sheets),它是用来进行网页风格设计的.通俗的说就是进行网页美化的,没有html依然存在,多了css 它会更好.但是没有html,css就 ...

  9. 入门git

    入门git   0x01前言 既然没有华丽的出场,那就平凡的分享,首先我要说明一点本篇文章针对Git初学者,对我自己学Git的资源的整合,其实本篇索引应该在我写Git系列文章的时候就紧跟着放上索引的, ...

  10. NETSH WINSOCK RESET这个命令的意义和效果?

    简要地netsh winsock reset命令含义复位 Winsock 文件夹.一机多用的假设Winsock协议配置问题,那么问题会导致网络连接,我们需要使用netsh winsock reset命 ...