您的位置:首页 > 其它

照片墙的实现原理

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.

一个包含了一定数目值的强引用的缓冲区。每次当一个值到达的时候,它移到队列的最前面。当队列满的时候,值到达,队列最后面的值将可能会被垃圾回收。。。。
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);

}
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: