B
BlupBlup
Ambitioniertes Mitglied
- 1
Hi,
ich habe versucht eine eigene Galerie zu programmieren,
basierend auf dem Android Tutorial Displaying Bitmaps in Your UI | Android Developers
Die Galerie ist mit einer GridView realisiert.
Die Galerie zeigt mir Bilder aus dem Verzeichnis "myPhotos" an.
Darin sind ungefähr 400 Bilder enthalten mit jeweils einer Größe zwischen 0,5 MB und 1 MB.
Sobald ich anfange langsam zu scrollen stürzt die App ab. So ca nach dem
ich vielleicht die hälfte oder das erste drittel der Bilder beim langsamen scrollen erreicht habe.
Vielleicht hat jemand von euch ja schonmal das entsprechende Tutorial
auf der Android Seite ebenfalls duchgearbeitet und weiß woran es liegen könnte.
Er besteht aus den fünf Dateien:
-PhaseOnePicture
-ImageAdapter
-AsyncDrawable
-BitmapWorkerTask
-ImageCache
ich habe versucht eine eigene Galerie zu programmieren,
basierend auf dem Android Tutorial Displaying Bitmaps in Your UI | Android Developers
Die Galerie ist mit einer GridView realisiert.
Die Galerie zeigt mir Bilder aus dem Verzeichnis "myPhotos" an.
Darin sind ungefähr 400 Bilder enthalten mit jeweils einer Größe zwischen 0,5 MB und 1 MB.
Sobald ich anfange langsam zu scrollen stürzt die App ab. So ca nach dem
ich vielleicht die hälfte oder das erste drittel der Bilder beim langsamen scrollen erreicht habe.
Vielleicht hat jemand von euch ja schonmal das entsprechende Tutorial
auf der Android Seite ebenfalls duchgearbeitet und weiß woran es liegen könnte.
Hier der Code:07-15 14:05:04.588: D/dalvikvm(13359): GC_CONCURRENT freed <1K, 36% free 29708K/46307K, paused 2ms+2ms
07-15 14:05:04.778: D/GETCOUNT(13359): 393
07-15 14:05:04.808: D/dalvikvm(13359): GC_FOR_ALLOC freed 14504K, 67% free 15348K/46307K, paused 18ms
07-15 14:05:04.828: I/dalvikvm-heap(13359): Grow heap (frag case) to 29.137MB for 14745616-byte allocation
07-15 14:05:04.858: D/dalvikvm(13359): GC_FOR_ALLOC freed <1K, 36% free 29747K/46307K, paused 17ms
07-15 14:05:04.898: D/dalvikvm(13359): GC_CONCURRENT freed <1K, 36% free 29749K/46307K, paused 1ms+3ms
07-15 14:05:05.158: D/GETCOUNT(13359): 393
07-15 14:05:05.188: D/dalvikvm(13359): GC_FOR_ALLOC freed 14506K, 67% free 15389K/46307K, paused 18ms
07-15 14:05:05.218: I/dalvikvm-heap(13359): Grow heap (frag case) to 29.177MB for 14745616-byte allocation
07-15 14:05:05.238: D/dalvikvm(13359): GC_FOR_ALLOC freed 1K, 36% free 29788K/46307K, paused 17ms
07-15 14:05:05.288: D/dalvikvm(13359): GC_CONCURRENT freed 1K, 36% free 29789K/46307K, paused 1ms+3ms
07-15 14:05:05.499: D/GETCOUNT(13359): 393
07-15 14:05:05.529: D/dalvikvm(13359): GC_FOR_ALLOC freed 14505K, 67% free 15429K/46307K, paused 17ms
07-15 14:05:05.559: I/dalvikvm-heap(13359): Grow heap (frag case) to 29.216MB for 14745616-byte allocation
07-15 14:05:05.589: D/dalvikvm(13359): GC_FOR_ALLOC freed <1K, 36% free 29829K/46307K, paused 20ms
07-15 14:05:05.639: D/dalvikvm(13359): GC_CONCURRENT freed <1K, 36% free 29828K/46307K, paused 2ms+5ms
07-15 14:05:05.779: D/GETCOUNT(13359): 393
07-15 14:05:05.809: D/dalvikvm(13359): GC_FOR_ALLOC freed 14503K, 67% free 15468K/46307K, paused 19ms
07-15 14:05:05.829: I/dalvikvm-heap(13359): Grow heap (frag case) to 29.254MB for 14745616-byte allocation
07-15 14:05:05.859: D/dalvikvm(13359): GC_FOR_ALLOC freed <1K, 36% free 29867K/46307K, paused 19ms
07-15 14:05:05.899: D/dalvikvm(13359): GC_CONCURRENT freed <1K, 36% free 29867K/46307K, paused 2ms+4ms
07-15 14:05:06.069: D/dalvikvm(13359): GC_FOR_ALLOC freed 14503K, 67% free 15507K/46307K, paused 21ms
07-15 14:05:06.089: I/dalvikvm-heap(13359): Grow heap (frag case) to 29.292MB for 14745616-byte allocation
07-15 14:05:06.119: D/dalvikvm(13359): GC_FOR_ALLOC freed <1K, 36% free 29907K/46307K, paused 19ms
07-15 14:05:06.139: D/GETCOUNT(13359): 393
07-15 14:05:06.169: D/dalvikvm(13359): GC_CONCURRENT freed 1K, 36% free 29907K/46307K, paused 2ms+3ms
07-15 14:05:06.339: D/GETCOUNT(13359): 393
07-15 14:05:06.369: D/dalvikvm(13359): GC_FOR_ALLOC freed 14504K, 67% free 15546K/46307K, paused 20ms
07-15 14:05:06.369: I/dalvikvm-heap(13359): Forcing collection of SoftReferences for 21219856-byte allocation
07-15 14:05:06.410: D/dalvikvm(13359): GC_BEFORE_OOM freed 8K, 67% free 15537K/46307K, paused 34ms
07-15 14:05:06.410: E/dalvikvm-heap(13359): Out of memory on a 21219856-byte allocation.
07-15 14:05:06.410: I/dalvikvm(13359): "AsyncTask #4" prio=5 tid=14 RUNNABLE
07-15 14:05:06.410: I/dalvikvm(13359): | group="main" sCount=0 dsCount=0 obj=0x41431db8 self=0x388ba8
07-15 14:05:06.410: I/dalvikvm(13359): | sysTid=13532 nice=10 sched=0/0 cgrp=bg_non_interactive handle=2700984
07-15 14:05:06.410: I/dalvikvm(13359): | schedstat=( 8477935751 2599548379 5546 ) utm=792 stm=55 core=0
07-15 14:05:06.410: I/dalvikvm(13359): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
07-15 14:05:06.410: I/dalvikvm(13359): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
07-15 14:05:06.410: I/dalvikvm(13359): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:305)
07-15 14:05:06.410: I/dalvikvm(13359): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:330)
07-15 14:05:06.410: I/dalvikvm(13359): at com.master.BitmapWorkerTask.doInBackground(BitmapWorkerTask.java:28)
07-15 14:05:06.410: I/dalvikvm(13359): at com.master.BitmapWorkerTask.doInBackground(BitmapWorkerTask.java:1)
07-15 14:05:06.410: I/dalvikvm(13359): at android.os.AsyncTask$2.call(AsyncTask.java:264)
07-15 14:05:06.410: I/dalvikvm(13359): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-15 14:05:06.410: I/dalvikvm(13359): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-15 14:05:06.410: I/dalvikvm(13359): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
07-15 14:05:06.410: I/dalvikvm(13359): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-15 14:05:06.410: I/dalvikvm(13359): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-15 14:05:06.410: I/dalvikvm(13359): at java.lang.Thread.run(Thread.java:856)
07-15 14:05:06.410: D/skia(13359): --- decoder->decode returned false
07-15 14:05:06.410: W/dalvikvm(13359): threadid=14: thread exiting with uncaught exception (group=0x40acf210)
07-15 14:05:06.440: D/dalvikvm(13359): GC_FOR_ALLOC freed 34K, 67% free 15537K/46307K, paused 16ms
07-15 14:05:06.450: I/dalvikvm-heap(13359): Grow heap (frag case) to 29.322MB for 14745616-byte allocation
07-15 14:05:06.470: D/dalvikvm(13359): GC_FOR_ALLOC freed <1K, 36% free 29937K/46307K, paused 18ms
07-15 14:05:06.490: E/AndroidRuntime(13359): FATAL EXCEPTION: AsyncTask #4
07-15 14:05:06.490: E/AndroidRuntime(13359): java.lang.RuntimeException: An error occured while executing doInBackground()
07-15 14:05:06.490: E/AndroidRuntime(13359): at android.os.AsyncTask$3.done(AsyncTask.java:278)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-15 14:05:06.490: E/AndroidRuntime(13359): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.lang.Thread.run(Thread.java:856)
07-15 14:05:06.490: E/AndroidRuntime(13359): Caused by: java.lang.OutOfMemoryError
07-15 14:05:06.490: E/AndroidRuntime(13359): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
07-15 14:05:06.490: E/AndroidRuntime(13359): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
07-15 14:05:06.490: E/AndroidRuntime(13359): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:305)
07-15 14:05:06.490: E/AndroidRuntime(13359): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:330)
07-15 14:05:06.490: E/AndroidRuntime(13359): at com.master.BitmapWorkerTask.doInBackground(BitmapWorkerTask.java:28)
07-15 14:05:06.490: E/AndroidRuntime(13359): at com.master.BitmapWorkerTask.doInBackground(BitmapWorkerTask.java:1)
07-15 14:05:06.490: E/AndroidRuntime(13359): at android.os.AsyncTask$2.call(AsyncTask.java:264)
07-15 14:05:06.490: E/AndroidRuntime(13359): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-15 14:05:06.490: E/AndroidRuntime(13359): ... 5 more
07-15 14:05:06.500: D/dalvikvm(13359): GC_CONCURRENT freed 23K, 36% free 29947K/46307K, paused 2ms+4ms
Er besteht aus den fünf Dateien:
-PhaseOnePicture
-ImageAdapter
-AsyncDrawable
-BitmapWorkerTask
-ImageCache
Code:
public class PhaseOnePicture extends Activity
{
private String TAG = "PhaseOnePicture";
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phase_one_picture);
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(PhaseOnePicture.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
}
}
Code:
public class ImageAdapter extends BaseAdapter
{
private Context mContext;
private File[] files;
private Bitmap mPlaceHolderBitmap;
private ImageCache imageCache;
public ImageAdapter(Context c)
{
this.mContext = c;
this.mPlaceHolderBitmap = BitmapFactory.decodeResource(this.mContext.getResources(), R.drawable.empty_photo);
File dir = new File(Environment.getExternalStorageDirectory().toString() + "/myPhotos");
this.imageCache = new ImageCache();
this.files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename)
{
if ((!filename.toLowerCase().endsWith(".jpg")) && (!filename.toLowerCase().endsWith(".png")) && (!filename.toLowerCase().endsWith(".gif")))
{
return false;
}
File f = new File(dir, filename);
return f.canRead() && !f.isDirectory();
}
});
}
@Override
public int getCount()
{
return this.files.length;
}
@Override
public Object getItem(int position)
{
return this.files[position].getAbsolutePath();
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView imageView;
if (convertView == null)
{
imageView = new ImageView(this.mContext);
imageView.setLayoutParams(new GridView.LayoutParams(100, 100));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
}
else
{
imageView = (ImageView) convertView;
}
this.loadBitmap((String)this.getItem(position), imageView);
return imageView;
}
private void loadBitmap(String filePath, ImageView imageView)
{
if (this.cancelPotentialWork(filePath, imageView))
{
final Bitmap bitmap = this.imageCache.getBitmapFromMemCache(String.valueOf(filePath));
if (bitmap != null)
{
imageView.setImageBitmap(bitmap);
}
else
{
final BitmapWorkerTask task = new BitmapWorkerTask(imageView, this.imageCache);
final AsyncDrawable asyncDrawable = new AsyncDrawable(this.mContext.getResources(), this.mPlaceHolderBitmap, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(filePath);
}
}
}
private boolean cancelPotentialWork(String filePath, ImageView imageView)
{
final BitmapWorkerTask bitmapWorkerTask = BitmapWorkerTask.getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null)
{
if (!bitmapWorkerTask.getFilePath().equals(filePath))
{
bitmapWorkerTask.cancel(true);
}
else
{
return false;
}
}
return true;
}
}
Code:
public class AsyncDrawable extends BitmapDrawable
{
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask)
{
super(res, bitmap);
this.bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask()
{
return this.bitmapWorkerTaskReference.get();
}
}
Code:
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap>
{
private final WeakReference<ImageView> imageViewReference;
private String filePath = "";
private ImageCache imageCache;
public BitmapWorkerTask(ImageView imageView, ImageCache imageCache)
{
this.imageViewReference = new WeakReference<ImageView>(imageView);
this.imageCache = imageCache;
}
@Override
protected Bitmap doInBackground(String... params)
{
this.filePath = params[0];
Bitmap thumbImage = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filePath), 100, 100);
this.imageCache.addBitmapToMemoryCache(this.filePath, thumbImage);
return thumbImage;
}
@Override
protected void onPostExecute(Bitmap bitmap)
{
if (isCancelled())
{
bitmap = null;
}
if (this.imageViewReference != null && bitmap != null)
{
final ImageView imageView = this.imageViewReference.get();
final BitmapWorkerTask bitmapWorkerTask = BitmapWorkerTask.getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null)
{
imageView.setImageBitmap(bitmap);
}
}
}
public static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView)
{
if (imageView != null)
{
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable)
{
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
public String getFilePath()
{
return this.filePath;
}
}
Code:
public class ImageCache
{
private LruCache<String, Bitmap> mMemoryCache;
private String TAG = "ImageCache";
public ImageCache()
{
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
this.mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount() / 1024;
}
};
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap)
{
if (getBitmapFromMemCache(key) == null)
{
this.mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key)
{
return this.mMemoryCache.get(key);
}
}