照片墙的实现原理
2014-04-23 10:59
281 查看
首先,这篇文章参照大神的文章,这里只是相当于自己的学习笔记吧。原文:点击打开链接
首先,在很多时候,当我们在使用GridView加载的时候,我们需要加载很多的item,其中每个Item都可能包含有图片。图片加载多了就容易OOM。所以,利用LruCache来避免OOM是一种不错的方法。它使得内存中的图片始终维持在一个固定的水平。。。以下是代码的实现过程。
这里中涉及到的几个重点:
第一是LruCache。这是官方API:
A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head
of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection.
一个包含了一定数目值的强引用的缓冲区。每次当一个值到达的时候,它移到队列的最前面。当队列满的时候,值到达,队列最后面的值将可能会被垃圾回收。。。。
首先,在很多时候,当我们在使用GridView加载的时候,我们需要加载很多的item,其中每个Item都可能包含有图片。图片加载多了就容易OOM。所以,利用LruCache来避免OOM是一种不错的方法。它使得内存中的图片始终维持在一个固定的水平。。。以下是代码的实现过程。
这里中涉及到的几个重点:
第一是LruCache。这是官方API:
A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head
of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection.
一个包含了一定数目值的强引用的缓冲区。每次当一个值到达的时候,它移到队列的最前面。当队列满的时候,值到达,队列最后面的值将可能会被垃圾回收。。。。
public class PhoneWallAdapter extends ArrayAdapter<String> implements OnScrollListener { //第一个可见的下标 int firstVisibleItem; //一屏加载的数目,实现当图片数目多于屏幕可加载的数量时,多余的暂时不加载 int visibleItemCount; //用于缓存图片的内存大小 int mMemoryCache; //存放下载任务的集合 HashSet<DownLoadTask> taskSet; //一个存放图片引用的队列。。。当队列中缓冲区满时,队尾的引用会被自动回收。。。。 LruCache<String,Bitmap>mLruCache; Context context; GridView gridView; boolean isFirstEnter=true; String []path; public PhoneWallAdapter(Context context, int textViewResourceId,String[]path,GridView gridView) { super(context, textViewResourceId); this.context=context; this.gridView=gridView; this.path=path; taskSet=new HashSet<DownLoadTask>(); mMemoryCache=(int)Runtime.getRuntime().maxMemory()/8; mLruCache=new LruCache<String,Bitmap>(mMemoryCache){ @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getByteCount(); } }; this.gridView.setOnScrollListener(this); } @Override public int getCount() { return path.length; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; String url=path[position]; if(convertView==null) { LayoutInflater inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view=inflater.inflate(R.layout.image, null); } else { view=convertView; } ImageView iv=(ImageView) view.findViewById(R.id.image); //给ImageView添加标记。这样就可以通过tag来定位了。 iv.setTag(url); setImageView(url,iv); return view; } private void setImageView(String url, ImageView iv) { //从缓冲区中加载图片,没有的话就设置为默认的图片 Bitmap mBitmap=getBitmapFromCache(url); if(mBitmap==null) { iv.setImageResource(R.drawable.empty_photo); } else { iv.setImageBitmap(mBitmap); } } private void addBitmapToCache(String url,Bitmap mBitmap) { //将图片加载到缓冲区中 if(getBitmapFromCache(url)==null) { mLruCache.put(url, mBitmap); } } private Bitmap getBitmapFromCache(String url) { return mLruCache.get(url); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { //不滑动的时候加载 if(scrollState==SCROLL_STATE_IDLE) { loadBitmaps(firstVisibleItem,visibleItemCount); }else {//滑动的时候取消下载 cancelAllTask(); } } private void loadBitmaps(int firstVisibleItem, int visibleItemCount) { for(int i=firstVisibleItem;i<firstVisibleItem+visibleItemCount;i++) { String tag=Images.imageThumbUrls[i]; Bitmap mBitmap=mLruCache.get(tag); if(mBitmap==null) { DownLoadTask loadTask=new DownLoadTask(); //将下载任务加入到集合中,下载完成后可以从集合中删除。 taskSet.add(loadTask); loadTask.execute(tag); }else { ImageView iv=(ImageView) gridView.findViewWithTag(tag); iv.setImageBitmap(mBitmap); } } } //在这里也许会迷糊,为什么在onScroll里面调用呢?看API。 @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.visibleItemCount=visibleItemCount; this.firstVisibleItem=firstVisibleItem; if(isFirstEnter==true&&visibleItemCount>0) { loadBitmaps(firstVisibleItem,visibleItemCount); isFirstEnter=false; } } public void cancelAllTask() { for(DownLoadTask task:taskSet) { task.cancel(false); } } public Bitmap downloadBitmap(String s) { InputStream is=null; try { URL url=new URL(s); HttpURLConnection conn=(HttpURLConnection) url.openConnection(); is=conn.getInputStream(); Bitmap mBitmap=BitmapFactory.decodeStream(is); return mBitmap; } catch(Exception e) { e.printStackTrace(); } finally { if(is!=null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } class DownLoadTask extends AsyncTask<String,Void,Bitmap> { private Bitmap mBitmap; private String tag; @Override protected Bitmap doInBackground(String... params) { try { tag=params[0]; mBitmap = downloadBitmap(tag); //将下载好的图片加入到LruCache对象中 addBitmapToCache(params[0], mBitmap); //图片下载完成后,将该图片的下载任务从集合中删除。 taskSet.remove(this); } catch (Exception e) { e.printStackTrace(); } return mBitmap; } @Override protected void onPostExecute(Bitmap result) { //通过tag来定位imageView ImageView view=(ImageView) gridView.findViewWithTag(tag); if(view!=null&&result!=null) { view.setImageBitmap(result); } } } }
相关文章推荐
- JVM系列七:JDK5.0中JVM堆模型、GC垃圾收集详细解析
- c字符处理之空字符、null与0
- VisualNet在综合布线设备管理中的优越性
- 【tomcat】eclipse配置好tomcat但是不能访问主页
- 什么是ISCSI,及Linux下怎么样通过ISCSI实现共享存储 推荐
- smartdraw 图表制作软件
- 一些好的工具
- JAVA基础:八进制,十六进制表示
- LR9系列安装报错解决(Setup has determined that a previous installation has not completed.)
- 【tomcat】eclipse配置好tomcat但是不能访问主页
- 关于VS中区分debug与release,32位与64位编译的宏定义
- 我的设计(目录)
- PPT设计的四重境界(上)
- php 调用.net的webservice 需要注意的
- JS.json对象转化
- 【原创】Ubuntu下更改root用户密码以及添加/删除用户
- vmware下redhat5.4添加分区及挂载
- IOS开发---常用函数和常数
- 两种情况下的Android应用退出代码
- 重大发现