好吧,從2天我很掙扎,請有人幫我解決這個問題。從sdcard將圖像加載到gridview拋出內存異常?
我想將外部存儲器中所有圖像的列表加載到我的gridview中。
我能夠使用此方法從系統中獲取圖像列表。
public static ArrayList<String> getFilePaths(Activity context)
{
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.ImageColumns.DATA};
Cursor c = null;
SortedSet<String> dirList = new TreeSet<String>();
ArrayList<String> resultIAV = new ArrayList<String>();
String[] directories = null;
if (u != null)
{
c = context.managedQuery(u, projection, null, null, null);
}
if ((c != null) && (c.moveToFirst()))
{
do
{
String tempDir = c.getString(0);
tempDir = tempDir.substring(0, tempDir.lastIndexOf("/"));
try{
dirList.add(tempDir);
}
catch(Exception e)
{
}
}
while (c.moveToNext());
directories = new String[dirList.size()];
dirList.toArray(directories);
}
for(int i=0;i<dirList.size();i++)
{
File imageDir = new File(directories[i]);
File[] imageList = imageDir.listFiles();
if(imageList == null)
continue;
for (File imagePath : imageList) {
try {
if(imagePath.isDirectory())
{
imageList = imagePath.listFiles();
}
if (imagePath.getName().contains(".jpg")|| imagePath.getName().contains(".JPG")
|| imagePath.getName().contains(".jpeg")|| imagePath.getName().contains(".JPEG")
|| imagePath.getName().contains(".png") || imagePath.getName().contains(".PNG")
|| imagePath.getName().contains(".gif") || imagePath.getName().contains(".GIF")
|| imagePath.getName().contains(".bmp") || imagePath.getName().contains(".BMP")
)
{
String path= imagePath.getAbsolutePath();
resultIAV.add(path);
}
}
// }
catch (Exception e) {
e.printStackTrace();
}
}
}
return resultIAV;
}
現在最棘手的部分來了,我知道,因爲它吃了大量的內存,我可以不加載實際圖像,並最終得到一個bitmap Outofmemory exception
因此,我有執行的圖像加載器,在一個單獨的執行圖像加載線程和加載圖像異步這裏是圖像加載器。
public class AbstractImageLoader {
private static ExecutorService executorService;
private static AbstractImageLoader loader;
public static int maxWidth;
Handler handler;;
private Map<ImageView,String> imageViews;
static {
AbstractImageLoader.executorService = Executors.newFixedThreadPool(5);
}
public AbstractImageLoader(final Context context) {
this.imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
this.handler = new Handler();
AbstractImageLoader.maxWidth = context.getResources().getDisplayMetrics().widthPixels/3;
}
public static AbstractImageLoader getInstance(final Context context) {
if (AbstractImageLoader.loader == null) {
AbstractImageLoader.loader = new AbstractImageLoader(context);
}
return AbstractImageLoader.loader;
}
private void queuePhoto(final String s, final ImageView imageView, final int n) {
AbstractImageLoader.executorService.submit(new PhotosLoader(new PhotoToLoad(s, imageView, n)));
}
public void DisplayImage(final String s, final ImageView imageView) {
this.DisplayImage(s, imageView, -1);
}
public void DisplayImage(final String s, final ImageView imageView, final int imageResource) {
this.imageViews.put(imageView, s);
final Bitmap value = MemCache.get(s);
if (value != null) {
imageView.setImageBitmap(value);
return;
}
this.queuePhoto(s, imageView, imageResource);
if (imageResource > -1) {
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setImageResource(imageResource);
return;
}
imageView.setImageDrawable((Drawable)null);
}
public void DisplayImage(final String s, final ImageView imageView, final Drawable imageDrawable) {
this.imageViews.put(imageView, s);
final Bitmap value = MemCache.get(s);
if (value != null) {
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageBitmap(value);
}
else {
this.queuePhoto(s, imageView, -1);
if (imageDrawable != null) {
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setImageDrawable(imageDrawable);
}
}
}
public void clearCache() {
MemCache.clear();
}
public void delete(final String s) {
MemCache.remove(s);
}
protected Bitmap getBitmap(final String ex) {
final Bitmap bitmap = null;
final File file = new File((String)ex);
if (!file.exists()) {
final String[] list = file.getParentFile().list(new FileUtils$Filters$6());
Object o = bitmap;
if (list != null) {
if (list.length != 0) {
o = new File(file.getParent(), list[0]);
final String absolutePath = ((File)o).getAbsolutePath();
o = ThumbUtils.getThumbnail(absolutePath, AlbumViewLoader.maxWidth);
return ThumbUtils.getThumbnail((String)ex, AlbumViewLoader.maxWidth);
}
o = bitmap;
}
return (Bitmap)o;
}
return ThumbUtils.getThumbnail((String)ex, AlbumViewLoader.maxWidth);
}
boolean imageViewReused(final PhotoToLoad photoToLoad) {
final String s = imageViews.get(photoToLoad.imageView);
return s == null || !s.equals(photoToLoad.url);
}
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(final Bitmap bitmap, final PhotoToLoad photoToLoad) {
this.bitmap = bitmap;
this.photoToLoad = photoToLoad;
}
@Override
public void run() {
if (!AbstractImageLoader.this.imageViewReused(this.photoToLoad)) {
if (this.bitmap != null) {
this.photoToLoad.imageView.setImageBitmap(this.bitmap);
this.photoToLoad.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return;
}
if (this.photoToLoad.placeholder_stub > -1) {
this.photoToLoad.imageView.setImageResource(this.photoToLoad.placeholder_stub);
this.photoToLoad.imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
}
}
}
}
private class PhotoToLoad
{
public ImageView imageView;
public int placeholder_stub;
public String url;
public PhotoToLoad(final String url, final ImageView imageView, final int placeholder_stub) {
this.url = url;
this.imageView = imageView;
this.placeholder_stub = placeholder_stub;
}
}
class PhotosLoader implements Runnable
{
PhotoToLoad photoToLoad;
PhotosLoader(final PhotoToLoad photoToLoad) {
this.photoToLoad = photoToLoad;
}
@Override
public void run() {
try {
/* if (!imageViewReused(this.photoToLoad)) {
return;
}*/
final Bitmap bitmap = AbstractImageLoader.this.getBitmap(this.photoToLoad.url);
if (bitmap != null) {
MemCache.put(this.photoToLoad.url, bitmap);
}
AbstractImageLoader.this.handler.post((Runnable)new BitmapDisplayer(bitmap, this.photoToLoad));
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
}
這裏是我創建的工具類的位圖:
public static Bitmap getThumbnail(final String s, int n) {
final BitmapFactory.Options bitmapFactory$Options = new BitmapFactory.Options();
bitmapFactory$Options.inSampleSize = 1;
bitmapFactory$Options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(s, bitmapFactory$Options);
if (bitmapFactory$Options.mCancel || bitmapFactory$Options.outWidth == -1 || bitmapFactory$Options.outHeight == -1) {
return null;
}
final int outHeight = bitmapFactory$Options.outHeight;
final int outWidth = bitmapFactory$Options.outWidth;
final float max = Math.max(n/outWidth, n/outHeight);
n = (int)(outWidth * max);
final int n2 = (int)(outHeight * max);
bitmapFactory$Options.inSampleSize = calculateInSampleSize(bitmapFactory$Options, n, n);
bitmapFactory$Options.inJustDecodeBounds = false;
bitmapFactory$Options.inDither = true;
bitmapFactory$Options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bmp = BitmapFactory.decodeFile(s, bitmapFactory$Options);
return ThumbnailUtils.extractThumbnail(bmp, n, n, 2);
}
因此,這裏是我的問題:
1.In我的縮略圖工具方法計算:
final float max = Math.max(n/outWidth, n/outHeight);
n = (int)(outWidth * max);
final int n2 = (int)(outHeight * max);
n總是返回爲0.因此縮略圖沒有被加載,所以暫時我硬編碼到212和縮略圖加載啓動
但加載特定數量的圖像後,我仍然得到out of memory exception
這裏是logcat的:
java.lang.OutOfMemoryError: Failed to allocate a 347790 byte allocation with 294944 free bytes and 288KB until OOM
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:639)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:615)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:391)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at com.geekmk.audiofx.test.ThumbUtils.getThumbnail(ThumbUtils.java:66)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at com.geekmk.audiofx.test.AbstractImageLoader.getBitmap(AbstractImageLoader.java:110)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at com.geekmk.audiofx.test.AbstractImageLoader$PhotosLoader.run(AbstractImageLoader.java:171)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
05-10 09:57:19.448 22498-22683/com.geekmk.audiofx W/System.err: at java.lang.Thread.run(Thread.java:818)
請幫我 在此先感謝。
你真的幾乎沒有堆空間。加載較少的圖像。在可以的地方回收'Bitmap'對象(參見'BitmapFactory.Options'的'inBitmap')。允許「Bitmap」對象在不再需要時被垃圾回收,並且不能被回收。 – CommonsWare
回收Bitmap對象?你能給我一個參考鏈接或解釋如何解決這個問題嗎? – Manikanta
http://developer.android.com/training/displaying-bitmaps/manage-memory.html http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inBitmap – CommonsWare