MainActivity如下:

  1. import android.os.Bundle;
  2. import android.widget.GridView;
  3. import android.app.Activity;
  4. /**
  5. * Demo描述:
  6. * 在GridView中采用LruCache异步加载大量图片,避免OOM
  7. *
  8. * 学习资料:
  9. * http://blog.csdn.net/guolin_blog/article/details/9526203
  10. * Thank you very much
  11. */
  12. public class MainActivity extends Activity {
  13. private GridView mGridView;
  14. private GridViewAdapter mGridViewAdapter;
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.main);
  19. init();
  20. }
  21. private void init(){
  22. mGridView = (GridView) findViewById(R.id.gridView);
  23. mGridViewAdapter = new GridViewAdapter(this, 0, ImagesUrl.Urls, mGridView);
  24. mGridView.setAdapter(mGridViewAdapter);
  25. }
  26. //取消所有的下载任务
  27. @Override
  28. protected void onDestroy() {
  29. super.onDestroy();
  30. mGridViewAdapter.cancelAllTasks();
  31. }

GridViewAdapter如下:

  1. import java.net.HttpURLConnection;
  2. import java.net.URL;
  3. import java.util.HashSet;
  4. import android.annotation.SuppressLint;
  5. import android.content.Context;
  6. import android.graphics.Bitmap;
  7. import android.graphics.BitmapFactory;
  8. import android.os.AsyncTask;
  9. import android.support.v4.util.LruCache;
  10. import android.view.LayoutInflater;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.widget.AbsListView;
  14. import android.widget.AbsListView.OnScrollListener;
  15. import android.widget.ArrayAdapter;
  16. import android.widget.GridView;
  17. import android.widget.ImageView;
  18. /**
  19. * LruCache的流程分析:
  20. * 我们从第一次进入应用的情况下开始
  21. * 1 依据图片的Url从LruCache缓存中取图片.
  22. *   若图片存在缓存中,则显示该图片;否则显示默认图片
  23. * 2 因为是第一次进入该界面所以会执行:
  24. *   loadBitmaps(firstVisibleItem, visibleItemCount);
  25. *   我们从loadBitmaps()方法作为切入点,继续往下梳理
  26. * 3 尝试从LruCache缓存中取图片.如果在显示即可,否则进入4
  27. * 4 开启一个异步任务下载图片.下载完成后显示图片,并且将
  28. *   该图片存入LruCache缓存中
  29. *
  30. * 在停止滑动时,会调用loadBitmaps(firstVisibleItem, visibleItemCount)
  31. * 情况与上类似
  32. */
  33. @SuppressLint("NewApi")
  34. public class GridViewAdapter extends ArrayAdapter<String> {
  35. private GridView mGridView;
  36. //图片缓存类
  37. private LruCache<String, Bitmap> mLruCache;
  38. //记录所有正在下载或等待下载的任务
  39. private HashSet<DownloadBitmapAsyncTask> mDownloadBitmapAsyncTaskHashSet;
  40. //GridView中可见的第一张图片的下标
  41. private int mFirstVisibleItem;
  42. //GridView中可见的图片的数量
  43. private int mVisibleItemCount;
  44. //记录是否是第一次进入该界面
  45. private boolean isFirstEnterThisActivity = true;
  46. public GridViewAdapter(Context context, int textViewResourceId,String[] objects, GridView gridView) {
  47. super(context, textViewResourceId, objects);
  48. mGridView = gridView;
  49. mGridView.setOnScrollListener(new ScrollListenerImpl());
  50. mDownloadBitmapAsyncTaskHashSet = new HashSet<DownloadBitmapAsyncTask>();
  51. // 获取应用程序最大可用内存
  52. int maxMemory = (int) Runtime.getRuntime().maxMemory();
  53. // 设置图片缓存大小为maxMemory的1/6
  54. int cacheSize = maxMemory/6;
  55. mLruCache = new LruCache<String, Bitmap>(cacheSize) {
  56. @Override
  57. protected int sizeOf(String key, Bitmap bitmap) {
  58. return bitmap.getByteCount();
  59. }
  60. };
  61. }
  62. @Override
  63. public View getView(int position, View convertView, ViewGroup parent) {
  64. String url = getItem(position);
  65. View view;
  66. if (convertView == null) {
  67. view = LayoutInflater.from(getContext()).inflate(R.layout.gridview_item, null);
  68. } else {
  69. view = convertView;
  70. }
  71. ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
  72. //为该ImageView设置一个Tag,防止图片错位
  73. imageView.setTag(url);
  74. //为该ImageView设置显示的图片
  75. setImageForImageView(url, imageView);
  76. return view;
  77. }
  78. /**
  79. * 为ImageView设置图片(Image)
  80. * 1 从缓存中获取图片
  81. * 2 若图片不在缓存中则为其设置默认图片
  82. */
  83. private void setImageForImageView(String imageUrl, ImageView imageView) {
  84. Bitmap bitmap = getBitmapFromLruCache(imageUrl);
  85. if (bitmap != null) {
  86. imageView.setImageBitmap(bitmap);
  87. } else {
  88. imageView.setImageResource(R.drawable.default_image);
  89. }
  90. }
  91. /**
  92. * 将图片存储到LruCache
  93. */
  94. public void addBitmapToLruCache(String key, Bitmap bitmap) {
  95. if (getBitmapFromLruCache(key) == null) {
  96. mLruCache.put(key, bitmap);
  97. }
  98. }
  99. /**
  100. * 从LruCache缓存获取图片
  101. */
  102. public Bitmap getBitmapFromLruCache(String key) {
  103. return mLruCache.get(key);
  104. }
  105. /**
  106. * 为GridView的item加载图片
  107. *
  108. * @param firstVisibleItem
  109. * GridView中可见的第一张图片的下标
  110. *
  111. * @param visibleItemCount
  112. * GridView中可见的图片的数量
  113. *
  114. */
  115. private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
  116. try {
  117. for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
  118. String imageUrl = ImagesUrl.Urls[i];
  119. Bitmap bitmap = getBitmapFromLruCache(imageUrl);
  120. if (bitmap == null) {
  121. DownloadBitmapAsyncTask downloadBitmapAsyncTask = new DownloadBitmapAsyncTask();
  122. mDownloadBitmapAsyncTaskHashSet.add(downloadBitmapAsyncTask);
  123. downloadBitmapAsyncTask.execute(imageUrl);
  124. } else {
  125. //依据Tag找到对应的ImageView显示图片
  126. ImageView imageView = (ImageView) mGridView.findViewWithTag(imageUrl);
  127. if (imageView != null && bitmap != null) {
  128. imageView.setImageBitmap(bitmap);
  129. }
  130. }
  131. }
  132. } catch (Exception e) {
  133. e.printStackTrace();
  134. }
  135. }
  136. /**
  137. * 取消所有正在下载或等待下载的任务
  138. */
  139. public void cancelAllTasks() {
  140. if (mDownloadBitmapAsyncTaskHashSet != null) {
  141. for (DownloadBitmapAsyncTask task : mDownloadBitmapAsyncTaskHashSet) {
  142. task.cancel(false);
  143. }
  144. }
  145. }
  146. private class ScrollListenerImpl implements OnScrollListener{
  147. /**
  148. *
  149. * 我们的本意是通过onScrollStateChanged获知:每次GridView停止滑动时加载图片
  150. * 但是存在一个特殊情况:
  151. * 当第一次入应用的时候,此时并没有滑动屏幕的操作即不会调用onScrollStateChanged,但应该加载图片.
  152. * 所以在此处做一个特殊的处理.
  153. * 即代码:
  154. * if (isFirstEnterThisActivity && visibleItemCount > 0) {
  155. *      loadBitmaps(firstVisibleItem, visibleItemCount);
  156. *      isFirstEnterThisActivity = false;
  157. *    }
  158. *
  159. * ------------------------------------------------------------
  160. *
  161. * 其余的都是正常情况.
  162. * 所以我们需要不断保存:firstVisibleItem和visibleItemCount
  163. * 从而便于中在onScrollStateChanged()判断当停止滑动时加载图片
  164. *
  165. */
  166. @Override
  167. public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
  168. mFirstVisibleItem = firstVisibleItem;
  169. mVisibleItemCount = visibleItemCount;
  170. if (isFirstEnterThisActivity && visibleItemCount > 0) {
  171. loadBitmaps(firstVisibleItem, visibleItemCount);
  172. isFirstEnterThisActivity = false;
  173. }
  174. }
  175. /**
  176. *  GridView停止滑动时下载图片
  177. *  其余情况下取消所有正在下载或者等待下载的任务
  178. */
  179. @Override
  180. public void onScrollStateChanged(AbsListView view, int scrollState) {
  181. if (scrollState == SCROLL_STATE_IDLE) {
  182. loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
  183. } else {
  184. cancelAllTasks();
  185. }
  186. }
  187. }
  188. /**
  189. * 下载图片的异步任务
  190. */
  191. class DownloadBitmapAsyncTask extends AsyncTask<String, Void, Bitmap> {
  192. private String imageUrl;
  193. @Override
  194. protected Bitmap doInBackground(String... params) {
  195. imageUrl = params[0];
  196. Bitmap bitmap = downloadBitmap(params[0]);
  197. if (bitmap != null) {
  198. //下载完后,将其缓存到LrcCache
  199. addBitmapToLruCache(params[0], bitmap);
  200. }
  201. return bitmap;
  202. }
  203. @Override
  204. protected void onPostExecute(Bitmap bitmap) {
  205. super.onPostExecute(bitmap);
  206. //下载完成后,找到其对应的ImageView显示图片
  207. ImageView imageView = (ImageView) mGridView.findViewWithTag(imageUrl);
  208. if (imageView != null && bitmap != null) {
  209. imageView.setImageBitmap(bitmap);
  210. }
  211. mDownloadBitmapAsyncTaskHashSet.remove(this);
  212. }
  213. }
  214. // 获取Bitmap
  215. private Bitmap downloadBitmap(String imageUrl) {
  216. Bitmap bitmap = null;
  217. HttpURLConnection httpURLConnection = null;
  218. try {
  219. URL url = new URL(imageUrl);
  220. httpURLConnection = (HttpURLConnection) url.openConnection();
  221. httpURLConnection.setConnectTimeout(5 * 1000);
  222. httpURLConnection.setReadTimeout(10 * 1000);
  223. httpURLConnection.setDoInput(true);
  224. httpURLConnection.setDoOutput(true);
  225. bitmap = BitmapFactory.decodeStream(httpURLConnection.getInputStream());
  226. } catch (Exception e) {
  227. e.printStackTrace();
  228. } finally {
  229. if (httpURLConnection != null) {
  230. httpURLConnection.disconnect();
  231. }
  232. }
  233. return bitmap;
  234. }
  235. }

ImagesUrl如下:

  1. public class ImagesUrl {
  2. public final static String[] Urls = new String[] {
  3. "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s160-c/A%252520Photographer.jpg",
  4. "https://lh4.googleusercontent.com/--dq8niRp7W4/URquVgmXvgI/AAAAAAAAAbs/-gnuLQfNnBA/s160-c/A%252520Song%252520of%252520Ice%252520and%252520Fire.jpg",
  5. "https://lh5.googleusercontent.com/-7qZeDtRKFKc/URquWZT1gOI/AAAAAAAAAbs/hqWgteyNXsg/s160-c/Another%252520Rockaway%252520Sunset.jpg",
  6. "https://lh3.googleusercontent.com/--L0Km39l5J8/URquXHGcdNI/AAAAAAAAAbs/3ZrSJNrSomQ/s160-c/Antelope%252520Butte.jpg",
  7. "https://lh6.googleusercontent.com/-8HO-4vIFnlw/URquZnsFgtI/AAAAAAAAAbs/WT8jViTF7vw/s160-c/Antelope%252520Hallway.jpg",
  8. "https://lh4.googleusercontent.com/-WIuWgVcU3Qw/URqubRVcj4I/AAAAAAAAAbs/YvbwgGjwdIQ/s160-c/Antelope%252520Walls.jpg",
  9. "https://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s160-c/Apre%2525CC%252580s%252520la%252520Pluie.jpg"};

LruCache为GridView异步加载大量网络图片的更多相关文章

  1. 利用LruCache为GridView异步加载大量网络图片完整示例

    MainActivity如下: package cc.testlrucache; import android.os.Bundle; import android.widget.GridView; i ...

  2. Android异步加载访问网络图片-解析json

    来自:http://www.imooc.com/video/7871 推荐大家去学习这个视频,讲解的很不错. 慕课网提供了一个json网址可以用来学习:http://www.imooc.com/api ...

  3. Android GridView异步加载图片和加载大量图片时出现Out Of Memory问题

    我们在使用GridView或者ListView时,通常会遇到两个棘手的问题: 1.每个Item获取的数据所用的时间太长会导致程序长时间黑屏,更甚会导致程序ANR,也就是Application No R ...

  4. ListView与GridView异步加载图片

    原理很简单,主要是用到了回调方法,下面是异步加载图片的类 <span style="font-size:16px;">package com.xxx.xxx; impo ...

  5. android官方开源的高性能异步加载网络图片的Gridview例子

    这个是我在安卓安卓巴士上看到的资料,放到这儿共享下.这个例子android官方提供的,其中讲解了如何异步加载网络图片,以及在gridview中高效率的显示图片此代码很好的解决了加载大量图片时,报OOM ...

  6. Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...

  7. [置顶] 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

    转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<Strin ...

  8. wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...

  9. Android批量图片加载经典系列——使用LruCache、AsyncTask缓存并异步加载图片

    一.问题描述 使用LruCache.AsyncTask实现批量图片的加载并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)加载图片,并放入缓存中 2.及时移除 ...

随机推荐

  1. 使用Entity Framework通过code first方式创建数据库和数据表

    开发环境 WIN10 Entity Framework6.0  MVC5.0  开发工具 VS2015  SqlServer2012 1.创建上下文Context继承DbContext,并创建其他的业 ...

  2. Android 双击 Back 键退出程序

    双击退出程序的原理无非就是设置一个退出标识(询问是否退出),如果改变了这个标识(确认退出),则再次点击时立马退出,如果短时间内没有退出,则延时重置这个标识(不退出). ================ ...

  3. WebService -- Java 实现之 CXF ( 使用CXF工具生成client 程序)

    1. 下载CXF 工具解压到磁盘 2.添加工具bin目录到PATH环境变量 3.创建一个CXF client新项目 4. run -> cmd 到指定目录,并运行工具目录下的批处理 “wadl2 ...

  4. 在react native用到的javascript 的一些关键知识(整理中)

    发现了一个讲解javascript的好网站,分享一下,讲的非常棒! 注意,这些文章都可以选择中文进行阅读! 下面这个连接是关于prototype的: https://developer.mozilla ...

  5. 「转」xtrabackup新版详细说明

    声明:本文由我的同事@fiona514编写,是我看过的最用心的中文说明介绍,强烈推荐大家学习使用. Percona Xtrabackup 2.4.1 编译及软件依赖 centos5,6 需要升级cma ...

  6. .NET LINQ 相等运算

    相等运算      如果两个序列的对应元素相等且这两个序列具有相同数量的元素,则视这两个序列相等. 方法 方法名 说明 C# 查询表达式语法 Visual Basic 查询表达式语法 更多信息 Seq ...

  7. vue学习

    2016年12月2日 今天学习Vue.js,对于未知的知识,一脸懵逼.记录学习新知识的路程,为以后学习更多的新知识一个引导.以后学会了之后再回来看看, 回忆一下会与不会的区别在哪.这样以后学习可以更快 ...

  8. (转)Nginx SSL+tomcat集群,request.getScheme() 取到https正确的协议

    转自http://www.cnblogs.com/interdrp/p/4881785.html 最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,to ...

  9. WdatePicker.js开始日期和结束日期比较

    jQuery.validator.addMethod("endDate",       function(value, element) {           var start ...

  10. JavaScript链表

        //实现列表类     function list() {         this.listSize = 0;//元素个数 属性         this.pos = 0;//当前位置 属性 ...