LruCache为GridView异步加载大量网络图片
MainActivity如下:
- import android.os.Bundle;
- import android.widget.GridView;
- import android.app.Activity;
- /**
- * Demo描述:
- * 在GridView中采用LruCache异步加载大量图片,避免OOM
- *
- * 学习资料:
- * http://blog.csdn.net/guolin_blog/article/details/9526203
- * Thank you very much
- */
- public class MainActivity extends Activity {
- private GridView mGridView;
- private GridViewAdapter mGridViewAdapter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- init();
- }
- private void init(){
- mGridView = (GridView) findViewById(R.id.gridView);
- mGridViewAdapter = new GridViewAdapter(this, 0, ImagesUrl.Urls, mGridView);
- mGridView.setAdapter(mGridViewAdapter);
- }
- //取消所有的下载任务
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mGridViewAdapter.cancelAllTasks();
- }
GridViewAdapter如下:
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.HashSet;
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.os.AsyncTask;
- import android.support.v4.util.LruCache;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AbsListView;
- import android.widget.AbsListView.OnScrollListener;
- import android.widget.ArrayAdapter;
- import android.widget.GridView;
- import android.widget.ImageView;
- /**
- * LruCache的流程分析:
- * 我们从第一次进入应用的情况下开始
- * 1 依据图片的Url从LruCache缓存中取图片.
- * 若图片存在缓存中,则显示该图片;否则显示默认图片
- * 2 因为是第一次进入该界面所以会执行:
- * loadBitmaps(firstVisibleItem, visibleItemCount);
- * 我们从loadBitmaps()方法作为切入点,继续往下梳理
- * 3 尝试从LruCache缓存中取图片.如果在显示即可,否则进入4
- * 4 开启一个异步任务下载图片.下载完成后显示图片,并且将
- * 该图片存入LruCache缓存中
- *
- * 在停止滑动时,会调用loadBitmaps(firstVisibleItem, visibleItemCount)
- * 情况与上类似
- */
- @SuppressLint("NewApi")
- public class GridViewAdapter extends ArrayAdapter<String> {
- private GridView mGridView;
- //图片缓存类
- private LruCache<String, Bitmap> mLruCache;
- //记录所有正在下载或等待下载的任务
- private HashSet<DownloadBitmapAsyncTask> mDownloadBitmapAsyncTaskHashSet;
- //GridView中可见的第一张图片的下标
- private int mFirstVisibleItem;
- //GridView中可见的图片的数量
- private int mVisibleItemCount;
- //记录是否是第一次进入该界面
- private boolean isFirstEnterThisActivity = true;
- public GridViewAdapter(Context context, int textViewResourceId,String[] objects, GridView gridView) {
- super(context, textViewResourceId, objects);
- mGridView = gridView;
- mGridView.setOnScrollListener(new ScrollListenerImpl());
- mDownloadBitmapAsyncTaskHashSet = new HashSet<DownloadBitmapAsyncTask>();
- // 获取应用程序最大可用内存
- int maxMemory = (int) Runtime.getRuntime().maxMemory();
- // 设置图片缓存大小为maxMemory的1/6
- int cacheSize = maxMemory/6;
- mLruCache = new LruCache<String, Bitmap>(cacheSize) {
- @Override
- protected int sizeOf(String key, Bitmap bitmap) {
- return bitmap.getByteCount();
- }
- };
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- String url = getItem(position);
- View view;
- if (convertView == null) {
- view = LayoutInflater.from(getContext()).inflate(R.layout.gridview_item, null);
- } else {
- view = convertView;
- }
- ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
- //为该ImageView设置一个Tag,防止图片错位
- imageView.setTag(url);
- //为该ImageView设置显示的图片
- setImageForImageView(url, imageView);
- return view;
- }
- /**
- * 为ImageView设置图片(Image)
- * 1 从缓存中获取图片
- * 2 若图片不在缓存中则为其设置默认图片
- */
- private void setImageForImageView(String imageUrl, ImageView imageView) {
- Bitmap bitmap = getBitmapFromLruCache(imageUrl);
- if (bitmap != null) {
- imageView.setImageBitmap(bitmap);
- } else {
- imageView.setImageResource(R.drawable.default_image);
- }
- }
- /**
- * 将图片存储到LruCache
- */
- public void addBitmapToLruCache(String key, Bitmap bitmap) {
- if (getBitmapFromLruCache(key) == null) {
- mLruCache.put(key, bitmap);
- }
- }
- /**
- * 从LruCache缓存获取图片
- */
- public Bitmap getBitmapFromLruCache(String key) {
- return mLruCache.get(key);
- }
- /**
- * 为GridView的item加载图片
- *
- * @param firstVisibleItem
- * GridView中可见的第一张图片的下标
- *
- * @param visibleItemCount
- * GridView中可见的图片的数量
- *
- */
- private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
- try {
- for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
- String imageUrl = ImagesUrl.Urls[i];
- Bitmap bitmap = getBitmapFromLruCache(imageUrl);
- if (bitmap == null) {
- DownloadBitmapAsyncTask downloadBitmapAsyncTask = new DownloadBitmapAsyncTask();
- mDownloadBitmapAsyncTaskHashSet.add(downloadBitmapAsyncTask);
- downloadBitmapAsyncTask.execute(imageUrl);
- } else {
- //依据Tag找到对应的ImageView显示图片
- ImageView imageView = (ImageView) mGridView.findViewWithTag(imageUrl);
- if (imageView != null && bitmap != null) {
- imageView.setImageBitmap(bitmap);
- }
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 取消所有正在下载或等待下载的任务
- */
- public void cancelAllTasks() {
- if (mDownloadBitmapAsyncTaskHashSet != null) {
- for (DownloadBitmapAsyncTask task : mDownloadBitmapAsyncTaskHashSet) {
- task.cancel(false);
- }
- }
- }
- private class ScrollListenerImpl implements OnScrollListener{
- /**
- *
- * 我们的本意是通过onScrollStateChanged获知:每次GridView停止滑动时加载图片
- * 但是存在一个特殊情况:
- * 当第一次入应用的时候,此时并没有滑动屏幕的操作即不会调用onScrollStateChanged,但应该加载图片.
- * 所以在此处做一个特殊的处理.
- * 即代码:
- * if (isFirstEnterThisActivity && visibleItemCount > 0) {
- * loadBitmaps(firstVisibleItem, visibleItemCount);
- * isFirstEnterThisActivity = false;
- * }
- *
- * ------------------------------------------------------------
- *
- * 其余的都是正常情况.
- * 所以我们需要不断保存:firstVisibleItem和visibleItemCount
- * 从而便于中在onScrollStateChanged()判断当停止滑动时加载图片
- *
- */
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
- mFirstVisibleItem = firstVisibleItem;
- mVisibleItemCount = visibleItemCount;
- if (isFirstEnterThisActivity && visibleItemCount > 0) {
- loadBitmaps(firstVisibleItem, visibleItemCount);
- isFirstEnterThisActivity = false;
- }
- }
- /**
- * GridView停止滑动时下载图片
- * 其余情况下取消所有正在下载或者等待下载的任务
- */
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- if (scrollState == SCROLL_STATE_IDLE) {
- loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
- } else {
- cancelAllTasks();
- }
- }
- }
- /**
- * 下载图片的异步任务
- */
- class DownloadBitmapAsyncTask extends AsyncTask<String, Void, Bitmap> {
- private String imageUrl;
- @Override
- protected Bitmap doInBackground(String... params) {
- imageUrl = params[0];
- Bitmap bitmap = downloadBitmap(params[0]);
- if (bitmap != null) {
- //下载完后,将其缓存到LrcCache
- addBitmapToLruCache(params[0], bitmap);
- }
- return bitmap;
- }
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- super.onPostExecute(bitmap);
- //下载完成后,找到其对应的ImageView显示图片
- ImageView imageView = (ImageView) mGridView.findViewWithTag(imageUrl);
- if (imageView != null && bitmap != null) {
- imageView.setImageBitmap(bitmap);
- }
- mDownloadBitmapAsyncTaskHashSet.remove(this);
- }
- }
- // 获取Bitmap
- private Bitmap downloadBitmap(String imageUrl) {
- Bitmap bitmap = null;
- HttpURLConnection httpURLConnection = null;
- try {
- URL url = new URL(imageUrl);
- httpURLConnection = (HttpURLConnection) url.openConnection();
- httpURLConnection.setConnectTimeout(5 * 1000);
- httpURLConnection.setReadTimeout(10 * 1000);
- httpURLConnection.setDoInput(true);
- httpURLConnection.setDoOutput(true);
- bitmap = BitmapFactory.decodeStream(httpURLConnection.getInputStream());
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (httpURLConnection != null) {
- httpURLConnection.disconnect();
- }
- }
- return bitmap;
- }
- }
ImagesUrl如下:
- public class ImagesUrl {
- public final static String[] Urls = new String[] {
- "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s160-c/A%252520Photographer.jpg",
- "https://lh4.googleusercontent.com/--dq8niRp7W4/URquVgmXvgI/AAAAAAAAAbs/-gnuLQfNnBA/s160-c/A%252520Song%252520of%252520Ice%252520and%252520Fire.jpg",
- "https://lh5.googleusercontent.com/-7qZeDtRKFKc/URquWZT1gOI/AAAAAAAAAbs/hqWgteyNXsg/s160-c/Another%252520Rockaway%252520Sunset.jpg",
- "https://lh3.googleusercontent.com/--L0Km39l5J8/URquXHGcdNI/AAAAAAAAAbs/3ZrSJNrSomQ/s160-c/Antelope%252520Butte.jpg",
- "https://lh6.googleusercontent.com/-8HO-4vIFnlw/URquZnsFgtI/AAAAAAAAAbs/WT8jViTF7vw/s160-c/Antelope%252520Hallway.jpg",
- "https://lh4.googleusercontent.com/-WIuWgVcU3Qw/URqubRVcj4I/AAAAAAAAAbs/YvbwgGjwdIQ/s160-c/Antelope%252520Walls.jpg",
- "https://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s160-c/Apre%2525CC%252580s%252520la%252520Pluie.jpg"};
}
LruCache为GridView异步加载大量网络图片的更多相关文章
- 利用LruCache为GridView异步加载大量网络图片完整示例
MainActivity如下: package cc.testlrucache; import android.os.Bundle; import android.widget.GridView; i ...
- Android异步加载访问网络图片-解析json
来自:http://www.imooc.com/video/7871 推荐大家去学习这个视频,讲解的很不错. 慕课网提供了一个json网址可以用来学习:http://www.imooc.com/api ...
- Android GridView异步加载图片和加载大量图片时出现Out Of Memory问题
我们在使用GridView或者ListView时,通常会遇到两个棘手的问题: 1.每个Item获取的数据所用的时间太长会导致程序长时间黑屏,更甚会导致程序ANR,也就是Application No R ...
- ListView与GridView异步加载图片
原理很简单,主要是用到了回调方法,下面是异步加载图片的类 <span style="font-size:16px;">package com.xxx.xxx; impo ...
- android官方开源的高性能异步加载网络图片的Gridview例子
这个是我在安卓安卓巴士上看到的资料,放到这儿共享下.这个例子android官方提供的,其中讲解了如何异步加载网络图片,以及在gridview中高效率的显示图片此代码很好的解决了加载大量图片时,报OOM ...
- Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
Android 高手进阶(21) 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...
- [置顶] 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<Strin ...
- wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)
wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...
- Android批量图片加载经典系列——使用LruCache、AsyncTask缓存并异步加载图片
一.问题描述 使用LruCache.AsyncTask实现批量图片的加载并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)加载图片,并放入缓存中 2.及时移除 ...
随机推荐
- 使用Entity Framework通过code first方式创建数据库和数据表
开发环境 WIN10 Entity Framework6.0 MVC5.0 开发工具 VS2015 SqlServer2012 1.创建上下文Context继承DbContext,并创建其他的业 ...
- Android 双击 Back 键退出程序
双击退出程序的原理无非就是设置一个退出标识(询问是否退出),如果改变了这个标识(确认退出),则再次点击时立马退出,如果短时间内没有退出,则延时重置这个标识(不退出). ================ ...
- WebService -- Java 实现之 CXF ( 使用CXF工具生成client 程序)
1. 下载CXF 工具解压到磁盘 2.添加工具bin目录到PATH环境变量 3.创建一个CXF client新项目 4. run -> cmd 到指定目录,并运行工具目录下的批处理 “wadl2 ...
- 在react native用到的javascript 的一些关键知识(整理中)
发现了一个讲解javascript的好网站,分享一下,讲的非常棒! 注意,这些文章都可以选择中文进行阅读! 下面这个连接是关于prototype的: https://developer.mozilla ...
- 「转」xtrabackup新版详细说明
声明:本文由我的同事@fiona514编写,是我看过的最用心的中文说明介绍,强烈推荐大家学习使用. Percona Xtrabackup 2.4.1 编译及软件依赖 centos5,6 需要升级cma ...
- .NET LINQ 相等运算
相等运算 如果两个序列的对应元素相等且这两个序列具有相同数量的元素,则视这两个序列相等. 方法 方法名 说明 C# 查询表达式语法 Visual Basic 查询表达式语法 更多信息 Seq ...
- vue学习
2016年12月2日 今天学习Vue.js,对于未知的知识,一脸懵逼.记录学习新知识的路程,为以后学习更多的新知识一个引导.以后学会了之后再回来看看, 回忆一下会与不会的区别在哪.这样以后学习可以更快 ...
- (转)Nginx SSL+tomcat集群,request.getScheme() 取到https正确的协议
转自http://www.cnblogs.com/interdrp/p/4881785.html 最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,to ...
- WdatePicker.js开始日期和结束日期比较
jQuery.validator.addMethod("endDate", function(value, element) { var start ...
- JavaScript链表
//实现列表类 function list() { this.listSize = 0;//元素个数 属性 this.pos = 0;//当前位置 属性 ...