2013-07-15 10 views
10

Ich verwende imageLoader-Klasse, um Bilder von URL zu laden. Aber all diese Bilder werden in der Galerie unter dem Ordnernamen LazyList gespeichert. Es dauert bis zu 40 -100 MB Speicher. Aber ich möchte diese Bilder nicht laden, da sich die Benutzer möglicherweise unwohl fühlen. Entschuldigung für das schlechte Englisch.Imageloader-Klasse erstellt Lazylist-Ordner in der Galerie. Wie man es vermeidet

Alles funktioniert gut, aber es erstellt einen Ordner in der Galerie und zeigt alle Bilder, die von meiner App verwendet werden. Ich denke also, dass Nutzer sich durch meine App unwohl fühlen werden.

Hier ist mein Code von Imageloader und auch verbindet sie mit einigen anderen Klassen auch

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.abs__ab_bottom_transparent_light_holo; 

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 { 
     Bitmap bitmap = null; 
     URL imageUrl = new URL(url); 
     HttpURLConnection conn = (HttpURLConnection) imageUrl 
       .openConnection(); 
     conn.setConnectTimeout(30000); 
     conn.setReadTimeout(30000); 
     conn.setInstanceFollowRedirects(true); 
     InputStream is = conn.getInputStream(); 
     OutputStream os = new FileOutputStream(f); 
     Utils.CopyStream(is, os); 
     os.close(); 
     bitmap = decodeFile(f); 
     return bitmap; 
    } 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 = 100; 
     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.inSampleSize = scale; 
     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
    } catch (FileNotFoundException e) { 
    } 
    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); 
     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); 
     else 
      photoToLoad.imageView.setImageResource(stub_id); 
    } 
} 

public void clearCache() { 
    memoryCache.clear(); 
    fileCache.clear(); 
} 
} 
+1

Wenn Sie die Bilder auf der SD-Karte speichern, fügen Sie dem Ordner die Datei '.nomedia' hinzu. Siehe zum Beispiel http://StackOverflow.com/a/17800556 – ozbek

+0

@Shoerat Ja, es funktioniert ... aber das Problem ist, wenn ich bestimmtes Bild für den Benutzer zeigen möchte, die gespeichert werden, kann ich es von jetzt an nicht tun. Zuvor verlinke ich es direkt anstelle von URL –

Antwort

5

ich meine Lösung bekam durch meine FileCache Wechsel Klasse und Zielordner

public class FileCache { 
    private File cacheDir; 
    private File nomediaFile; 
    String NOMEDIA = " .nomedia"; 
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(Environment.getExternalStorageDirectory() 
       + "/mydir"); 
     if (cacheDir.mkdir()) { 
      nomediaFile = new File(
        Environment.getExternalStorageDirectory() + "/mydir/" 
          + NOMEDIA); 
      if (!nomediaFile.exists()) { 
       try { 
        nomediaFile.createNewFile(); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 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) 
    @SuppressWarnings("deprecation") 
    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(); 
} 
} 
1

Sie die droidQuery Bibliothek zu faul laden Bilder von URLs verwenden können, so dass sie dann auf einer Pro-Sitzung Basis zwischenzuspeichern. Sie können auch Ihren eigenen Cache-Speicher verwenden, z. B. SharedPreferences oder eine SQLite-Datenbank. Um die Bilder herunterzuladen, verwenden Sie die lange Hand-Methode:

$.ajax(new AjaxOptions().url("http://www.example.com") 
         .type("GET") 
         .dataType("image") 
         .timeout(30000) 
         .cache(true) 
         .cacheTimeout(600000)//milliseconds 
         //consider using .imageWidth() or .imageHeight() methods to control output size 
         .success(new Function() { 
          @Override 
          public void invoke($ droidQuery, Object... params) { 
           myImageView.setImageBitmap((Bitmap) params[0]); 
           //save raw bitmap across sessions, maybe. 
          } 
         }); 

Um Daten zu einem Datenbank zu speichern oder SharedPreferences, lesen Sie über die Dokumentation: http://developer.android.com/guide/topics/data/data-storage.html

+0

Ich konnte die Bilder anzeigen und speichern, aber das Problem ist: Sie werden in meiner Galerie angezeigt. Jedes Bild in meiner App kann in der Galerie gesehen werden und ich möchte nicht, dass es gemacht wird –