Hi ,
i am using following attached three class to download images in my list
view but when i display some of images on screen after that i got out of
memory error and hang the application.in my app i am download thousands of
images on a single screen. is it possible or not??.
Thanks
On Thursday, May 17, 2012 10:22:19 AM UTC+5:30, huberte wrote:
>
> I used the method from Renaud here
>
>
> http://stackoverflow.com/questions/7524725/android-passing-variable-from-intent-extra-to-imageview/10604079#10604079
>
> This works fine on 2.1 2.3 phone and AVD when I tunr the phone from
> landscpae to portrait and vice versa
>
> Not in 4.03 phone and AVD, I get a java.lang.OutOfMemoryError, note that
> my bitmap eg, my png file is only 189ko heavy
>
> 05-17 04:29:53.532: E/AndroidRuntime(1227): FATAL EXCEPTION: main
> 05-17 04:29:53.532: E/AndroidRuntime(1227): java.lang.OutOfMemoryError
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.nativeCreate(Native Method)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.createBitmap(Bitmap.java:6 05)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.createBitmap(Bitmap.java:551)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:524)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:374)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:404)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> com.android.fbd.Images.onCreate(Images.java:35)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.Activity.performCreate(Activity.java:4465)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3351)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.access$700(ActivityThread.java:123)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread$H.handleMessage(ActivityThread.java:1151)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.os.Handler.dispatchMessage(Handler.java:99)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.os.Looper.loop(Looper.java:137)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.main(ActivityThread.java:4424)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> java.lang.reflect.Method.invokeNative(Native Method)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> java.lang.reflect.Method.invoke(Method.java:511)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> dalvik.system.NativeStart.main(Native Method)
>
On Thursday, May 17, 2012 10:22:19 AM UTC+5:30, huberte wrote:
>
> I used the method from Renaud here
>
>
> http://stackoverflow.com/questions/7524725/android-passing-variable-from-intent-extra-to-imageview/10604079#10604079
>
> This works fine on 2.1 2.3 phone and AVD when I tunr the phone from
> landscpae to portrait and vice versa
>
> Not in 4.03 phone and AVD, I get a java.lang.OutOfMemoryError, note that
> my bitmap eg, my png file is only 189ko heavy
>
> 05-17 04:29:53.532: E/AndroidRuntime(1227): FATAL EXCEPTION: main
> 05-17 04:29:53.532: E/AndroidRuntime(1227): java.lang.OutOfMemoryError
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.nativeCreate(Native Method)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.createBitmap(Bitmap.java:6 05)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.createBitmap(Bitmap.java:551)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:524)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:374)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:404)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> com.android.fbd.Images.onCreate(Images.java:35)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.Activity.performCreate(Activity.java:4465)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3351)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.access$700(ActivityThread.java:123)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread$H.handleMessage(ActivityThread.java:1151)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.os.Handler.dispatchMessage(Handler.java:99)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.os.Looper.loop(Looper.java:137)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> android.app.ActivityThread.main(ActivityThread.java:4424)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> java.lang.reflect.Method.invokeNative(Native Method)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> java.lang.reflect.Method.invoke(Method.java:511)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
> 05-17 04:29:53.532: E/AndroidRuntime(1227): at
> dalvik.system.NativeStart.main(Native Method)
>
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
package utils;
import java.io.File;
import android.content.Context;
public class FileCache {
private File cacheDir;
public FileCache(Context context) {
// Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
cacheDir = new File(
android.os.Environment.getExternalStorageDirectory(),
"LazyList");
else
cacheDir = context.getCacheDir();
if (!cacheDir.exists())
cacheDir.mkdirs();
}
public File getFile(String url) {
// I identify images by hashcode. Not a perfect solution, good for the
// demo.
String filename = String.valueOf(url.hashCode());
// Another possible solution (thanks to grantland)
// String filename = URLEncoder.encode(url);
File f = new File(cacheDir, filename);
return f;
}
public void clear() {
File[] files = cacheDir.listFiles();
if (files == null)
return;
for (File f : files)
f.delete();
}
}
package utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.widget.ImageView;
import com.table.R;
public class ImageLoader {
MemoryCache memoryCache = new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews = Collections
.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
public ImageLoader(Context context) {
fileCache = new FileCache(context);
executorService = Executors.newFixedThreadPool(5);
}
final int stub_id = R.drawable.default_image;
public void DisplayImage(String url, ImageView imageView) {
imageViews.put(imageView, url);
Bitmap bitmap = memoryCache.get(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}
private void queuePhoto(String url, ImageView imageView) {
PhotoToLoad p = new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
}
private Bitmap getBitmap(String url) {
File f = fileCache.getFile(url);
// from SD cache
Bitmap b = decodeFile(f);
if (b != null)
return b;
// from web
try {
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(Constant.user_name,
Constant.password.toCharArray());
}
});
URL urll = new URL(url.toString());
HttpURLConnection connection = (HttpURLConnection) urll
.openConnection();
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setChunkedStreamingMode(1000 * 1024);
connection.setRequestProperty("Connection", "Keep-Alive");
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
// Log.e("Bitmap", "returned");
return myBitmap;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 10;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inPurgeable = true;
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
e.fillInStackTrace();
}
return null;
}
// Task for the queue
private class PhotoToLoad {
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i) {
url = u;
imageView = i;
}
}
class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad) {
this.photoToLoad = photoToLoad;
}
@Override
public void run() {
if (imageViewReused(photoToLoad))
return;
Bitmap bmp = getBitmap(photoToLoad.url);
// bmp = resizeImage(bmp,60,60);
// memoryCache.put(photoToLoad.url, bmp);
if (imageViewReused(photoToLoad))
return;
BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
Activity a = (Activity) photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
boolean imageViewReused(PhotoToLoad photoToLoad) {
String tag = imageViews.get(photoToLoad.imageView);
if (tag == null || !tag.equals(photoToLoad.url))
return true;
return false;
}
// Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable {
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
bitmap = b;
photoToLoad = p;
}
public void run() {
if (imageViewReused(photoToLoad))
return;
if (bitmap != null) {
photoToLoad.imageView.setImageBitmap(bitmap);
fileCache.clear();
} else
photoToLoad.imageView.setImageResource(stub_id);
}
}
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
public static Bitmap resizeImage(Bitmap bitmap, int w, int h) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = w;
int newHeight = h;
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height,
matrix, true);
return resizedBitmap;
}
}
package utils;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import android.graphics.Bitmap;
import android.util.Log;
public class MemoryCache {
private static final String TAG = "MemoryCache";
// private Map<String, Bitmap> cache = Collections
// .synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true));//
// Last
// argument
// true
// for
// LRU
// ordering
private HashMap<String, SoftReference<Bitmap>> cache;
private long size = 0;// current allocated size
private long limit = 1000000;// max memory in bytes
public MemoryCache() {
// use 25% of available heap size
setLimit(Runtime.getRuntime().maxMemory() / 4);
}
public void setLimit(long new_limit) {
limit = new_limit;
Log.i(TAG, "MemoryCache will use up to " + limit / 1024. / 1024. + "MB");
}
public Bitmap get(String id) {
try {
if (!cache.containsKey(id))
return null;
// NullPointerException sometimes happen here
// http://code.google.com/p/osmdroid/issues/detail?id=78
return cache.get(id).get();
} catch (NullPointerException ex) {
return null;
}
}
public void put(String id, Bitmap bitmap) {
try {
if (cache.containsKey(id))
// size -= getSizeInBytes(cache.get(id).get());
cache.put(id, new SoftReference<Bitmap>(bitmap));
// size += getSizeInBytes(bitmap);
checkSize();
} catch (Throwable th) {
th.printStackTrace();
}
}
public void checkSize() {
Log.i(TAG, "cache size=" + size + " length=" + cache.size());
if (size > limit) {
Iterator<Entry<String, SoftReference<Bitmap>>> iter = cache
.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, SoftReference<Bitmap>> entry = iter.next();
size -= getSizeInBytes(entry.getValue().get());
iter.remove();
if (size <= limit)
break;
}
Log.i(TAG, "Clean cache. New size " + cache.size());
}
}
public void clear() {
cache.clear();
}
long getSizeInBytes(Bitmap bitmap) {
if (bitmap == null)
return 0;
return bitmap.getRowBytes() * bitmap.getHeight();
}
}