[Problem: ImageView] Performance und Speicher

U

Unicate

Erfahrenes Mitglied
57
Hallo alle zusammen!

Ich habe eine GridView in der ich ImageView's lade. (Galery like)

Hier meine Lösungsversuche und das was ich nicht so gut daran fand:


  1. Cursoradapter
    • Normaler ext. CursorAdapter, welcher die Thumbnailpfade ausließt und daraus die Bitmap zum anzeigen erstellt.
    • Nachteile:
      • Die Images werden beim füllen der ImageViews immer wieder neu erstellt und somit sieht das ganze sehr Ruckelig aus, besonders beim scrollen
  2. Preloading
    • Wie 1. nur das alle Bilder vorher vorgeladen werden.
    • Nachteile:
      • Das kann bei vielen Bildern sehr lange dauern.
  3. Async Loading
    • Die Bilder werden dynamisch geladen. d.h. sie werden angezeigt sobald sie geladen werden. Sieht SEHR gut aus.
    • Nachteil:
      • Wenn es zu viele Bilder sind (Und ich weiß ja nicht von wie vielen man ausgehen kann), dann wird OutOfMemoryException geworfen.
  4. Async Loading 2
    • Bisher noch nicht versucht
    • Idee ist, nur die Bilder zu laden, die angezeigt werden, die anderen aus dem Speicher entfernen.
    • Vermutlicher Nachteil:
      • Beim scrollen dauert es immer ein wenig bis die Bilder angezeigt werden (nicht schön :( )
Wie Ihr sehr sind alle diese Lösungen nicht das Gelbe vom Ei. Es muss doch eine optimale Lösung geben.
Ich habe schon viele Lösungen gesehen (Standartgalerie z.B.)

Ich komm nicht weiter, habt Ihr eine Idee oder einen neuen Ansatz?
 
Hat noch niemand sowas gemacht?
mh... :(
 
In deiner GridView werden nur kleine Bilder angezeigt, oder? Thumbnails wären das, was ich als einfachste Lösung empfinden würde.
 
Ja, es werden nur Thumbnails angezeigt.
Ab so ca. 50 Thumbnails gibt es eine OutOfMemoryException.

Wo lädt die Galerieapplikation Ihre Minithumbs her?
Und wie handled die das mit dem Speicher?
 
Also erzeugst du Thumbnails, oder zeigst du das Bild einfach nur 50*50 an?
Ich bin der Meinung, dass es mit Bildern, die tatsächlich 50*50 groß sind, auch bis 1000 geht.
 
Ich schau ob es die Thumbnails gibt. Wenn es welche gibt, dann verwende ich diese. wenn nicht, dann erzeuge ich diese:

AsyncTask<Object, LoadedImage, Object>

PHP:
 @Override
    protected Object doInBackground(Object... params) {
        Bitmap bitmap = null;
        Uri uri = null;            
        Cursor cursor = _context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                null, 
                null,
                null,       
                null);
        if(null != cursor) {
            while(cursor.moveToNext()) {
                long imageId = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID));
                Cursor thumbCursor = 
                    MediaStore.Images.Thumbnails.
                        queryMiniThumbnail(_context.getContentResolver(),
                                imageId, 
                                MediaStore.Images.Thumbnails.MINI_KIND, 
                                null);
                if(null != thumbCursor) {
                    if(thumbCursor.moveToFirst()) {                        
                        long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Thumbnails._ID));
                        uri = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + id);
                        try {
                            bitmap = BitmapFactory.decodeStream(_context.getContentResolver().openInputStream(uri));
                            if (bitmap != null) {
                                publishProgress(new LoadedImage(bitmap, imageId));
                            }
                        } catch (IOException e) {
                            //Error fetching image, try to recover
                            Log.d(TAG, "Thumbnail for: " + imageId + " does not exist!");
                            try {
                                uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ""+ imageId);
                                Bitmap tmpBitmap = BitmapFactory.decodeStream(_context.getContentResolver().openInputStream(uri));
                                // 4:3
                                int height = (tmpBitmap.getHeight() > tmpBitmap.getWidth())?100:75;
                                int width = (tmpBitmap.getWidth() > tmpBitmap.getHeight())?100:75;
                                if(tmpBitmap.getWidth() == tmpBitmap.getHeight()) {
                                    height = 100;
                                    width = 100;
                                }
                                bitmap = Bitmap.createScaledBitmap(tmpBitmap, width, height, false);
                                tmpBitmap.recycle();
                                publishProgress(new LoadedImage(bitmap, imageId));
//                                
                            } catch (Exception fnfe) {
                                Log.e(TAG, "Error while creating thumbnail!", fnfe);
                            }
                        }
                        thumbCursor.close();
                    }
                }
            }
            cursor.close();
        }
 
Zuletzt bearbeitet:
Hast du mal geprüft ob createScaledBitmap auch wirklich ein kleineres (vom Speicher her) Bitmap erzeugt? Die Dokumentation dazu fällt ja eher dürftig aus. Ich würde tippen, dass es einfach nur staucht und nichts verkleinert (vielleicht auch deswegen keine Dokumentation :p)
 
Gute Idee, aber API 8 (Ich muss das in API 3 entwickeln)

Und ja, die Bitmaps sind um EINIGES kleiner als die normalen (3XX,2YY)
 
Unicate schrieb:
Gute Idee, aber API 8 (Ich muss das in API 3 entwickeln)

Und ja, die Bitmaps sind um EINIGES kleiner als die normalen (3XX,2YY)
Oh, habe ich gar nicht gesehen...

In Byte?
 
Pixel!
 
Gibt es denn hierzu schon etwas neues?

Ein paar codeschnipsel würden weiter helfen :thumbsup:
 

Ähnliche Themen

M
  • MikelKatzengreis
Antworten
5
Aufrufe
130
swa00
swa00
B
Antworten
6
Aufrufe
1.051
jogimuc
J
A
Antworten
10
Aufrufe
1.926
swa00
swa00
Zurück
Oben Unten