2013-07-15 15 views
10

Używam klasy imageLoader do ładowania obrazów z adresu URL. Ale te wszystkie obrazy są przechowywane w galerii przez nazwę folderu o nazwie LazyList. Zajmuje to 40 do 100 MB pamięci. Ale nie chcę ładować tych obrazów, ponieważ użytkownicy mogą odczuwać dyskomfort. Przepraszamy za zły angielski.Klasa Imageloader tworzy folder lazylist w galerii. Jak tego uniknąć

Wszystko działa dobrze, ale tworzy folder w galerii i pokazuje wszystkie obrazy używane przez moją aplikację. Więc czuję, że użytkownicy będą odczuwać dyskomfort w mojej aplikacji.

Oto mój kod imageLoader a także to linki z kilku innych klas nawet

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

Podczas zapisywania obrazów na karcie SD, dodaj plik '.nomedia' do folderu. Zobacz na przykład http://stackoverflow.com/a/17800556 – ozbek

+0

@ shoerat Tak, to działa ... ale problem polega na tym, że chcę pokazać konkretny obraz dla zapisanego użytkownika Nie mogę tego zrobić od teraz. Poprzednio łączyłem go bezpośrednio zamiast wywoływać url –

Odpowiedz

5

Dostałem rozwiązanie poprzez zmianę mojego FileCache Klasa i jej folder docelowy

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

można użyć biblioteki droidQuery do leniwych Załaduj zdjęcia z adresów URL, a następnie umieść je w cache dla poszczególnych sesji. Możesz także obsługiwać własne buforowanie, na przykład SharedPreferences lub bazę danych SQLite. Aby pobrać obrazy, należy użyć metody długo ręki:

$.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. 
          } 
         }); 

zapisać dane do bazy danych lub SharedPreferences, przeczytać dokumentację: http://developer.android.com/guide/topics/data/data-storage.html

+0

Mogłem wyświetlać i przechowywać obrazy, ale problem polega na tym, że są one wyświetlane w mojej galerii. Każdy obraz w mojej aplikacji można zobaczyć w galerii i nie chcę, aby to było zrobione –

Powiązane problemy