最近做android开发的时候遇到读取sdcard下面图片展示,在网上找了很多相关资料,最终得于解决。在这里首先感谢下互联网的朋友们。接下来我把我实现的代码贴出来和大家分享下。由于代码里面的注释写的很清楚。我就不再一一描述了。
package com.zhuyesoft.sgzs.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
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;
import com.zhuyesoft.sgzs.activity.R;
/**
* 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;
// GridView中可见的第一张图片的下标
private int mFirstVisibleItem;
// GridView中可见的图片的数量
private int mVisibleItemCount;
// 记录是否是第一次进入该界面
private boolean isFirstEnterThisActivity = true;
private String[] imageUrls;
public GridViewAdapter(Context context, int textViewResourceId,
String[] objects, GridView gridView) {
super(context, textViewResourceId, objects);
mGridView = gridView;
mGridView.setOnScrollListener(new ScrollListenerImpl());
imageUrls=objects;
// 获取应用程序最大可用内存
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.activity_view_photo_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 = imageUrls[i];
Bitmap bitmap = getBitmapFromLruCache(imageUrl);
if (bitmap == null) {
bitmap=BitmapFactory.decodeFile(imageUrl);
ImageView imageView = (ImageView) mGridView.findViewWithTag(imageUrl);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
//将从SDCard读取的图片添加到LruCache中
addBitmapToLruCache(imageUrl, bitmap);
} else {
// 依据Tag找到对应的ImageView显示图片
ImageView imageView = (ImageView) mGridView
.findViewWithTag(imageUrl);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
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) {
System.out.println("---> 第一次进入该界面");
loadBitmaps(firstVisibleItem, visibleItemCount);
isFirstEnterThisActivity = false;
}
}
/**
* GridView停止滑动时下载图片 其余情况下取消所有正在下载或者等待下载的任务
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
}
}
}
}
package cc.testlrucache;
import android.os.Bundle;
import android.widget.GridView;
import android.app.Activity;
/**
* Demo描述:
* Android利用LruCache为GridView加载大量本地图片完整示例,防止OOM
*
* 更多参考:
* http://blog.youkuaiyun.com/lfdfhl
*/
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, ImagesPath.IMAGES_PATH, mGridView);
mGridView.setAdapter(mGridViewAdapter);
}
}
package cc.testlrucache;
public class ImagesPath {
public final static String DIR="/mnt/sdcard/Test/";
public final static String[] IMAGES_PATH = new String[] {
DIR+"a.jpg",
DIR+"b.jpg",
DIR+"c.jpg",
DIR+"d.jpg",
DIR+"e.jpg",
DIR+"f.jpg",
DIR+"g.jpg",
DIR+"h.jpg",
DIR+"i.jpg",
DIR+"j.jpg",
DIR+"k.jpg",
DIR+"l.jpg",
DIR+"m.jpg",
DIR+"n.jpg",
DIR+"o.jpg",
DIR+"p.jpg",
DIR+"q.jpg",
DIR+"r.jpg",
DIR+"s.jpg",
DIR+"t.jpg",
DIR+"w.jpg",
DIR+"x.jpg",
DIR+"y.jpg",
DIR+"z.jpg",
DIR+"za.jpg",
DIR+"zb.jpg",
DIR+"zc.jpg",
DIR+"zd.jpg",
DIR+"ze.jpg",
DIR+"zf.jpg",
DIR+"zg.jpg",
DIR+"zh.jpg",
DIR+"zi.jpg",
DIR+"zj.jpg",
DIR+"zk.jpg",
DIR+"zl.jpg",
DIR+"zm.jpg"
};
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<GridView
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="100dip"
android:gravity="center"
android:numColumns="auto_fit"
android:layout_marginTop="5dip"
android:layout_below="@id/ll_vt_header"
android:stretchMode="columnWidth"
android:verticalSpacing="10dip" />
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/imageView"
android:layout_width="100dip"
android:layout_height="100dip"
android:src="@drawable/default_image"
android:layout_centerInParent="true"
/>
</RelativeLayout>
本文介绍了一个使用LruCache优化Android GridView加载本地图片的方法,通过缓存机制避免了大量图片加载时导致的内存溢出问题。代码示例包括GridViewAdapter的实现、图片缓存流程分析及加载图片的逻辑。
8161

被折叠的 条评论
为什么被折叠?



