2015-12-01 1 views
0

Я нашел код из Интернета для ленивой загрузки изображений, и я использовал его в своем приложении. У меня есть проблемы с пониманием кода. Я прочитал много других сообщений об этом, но никто не помог. Мои вопросы:Android ленивые загрузки изображений, неоднозначные точки?

  1. Согласно приведенному ниже коду, в какой момент метод getView возвращает представление? Я имею в виду, что приложение сначала устанавливает изображение по умолчанию, затем идет загрузка фактического изображения из url или кеша файлов. Поэтому логически getView должен возвращать представление два раза, один раз для изображения по умолчанию и один раз для фактического изображения. Это правда? Как проходит процедура?
  2. Что происходит внутри метода imageViewReused()? Каждая пара (imageView, url) помещается на карту сразу после ее вставки в процесс (DisplayImage), но позже в imageViewReused() она сравнивается с URL-адресом из той же самой пары imageView? Разве это не всегда так? Я знаю, что когда прокручивается listView, новый образ не создается, а тот, который запускается из listView, перерабатывается. Даже учитывая это, мы все же имеем пару с одним и тем же imageView, но новый url, который заменит старый url на карте. Итак, какова цель выражения if в imageViewReused()? Другими словами, что, если я опускаю оператор if, чтобы метод всегда возвращал false? Я сделал это на самом деле, и никакого эффекта не наблюдалось в производительности приложения!
  3. Прокрутка немного быстро или в течение 3 или более раз, приложение просто падает. LogCat говорит outOfMemoryException. Как с этим бороться? Обратите внимание, что шаблон шаблона используется в коде.

Ниже мой код:

public class ImageLoader { 

MemoryCache memoryCache = new MemoryCache(); 
FileCache fileCache; 
private Map<ImageView, String> imageViews = Collections 
     .synchronizedMap(new WeakHashMap<ImageView, String>()); 
ExecutorService executorService; 
Handler handler = new Handler(); 

public ImageLoader(Context context) { 
    fileCache = new FileCache(context); 
    executorService = Executors.newFixedThreadPool(5); 
} 

final int stub_id = R.drawable.profile; 

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(); 
     conn.disconnect(); 
     bitmap = decodeFile(f); 
     return bitmap; 
    } catch (Throwable ex) { 
     ex.printStackTrace(); 
     if (ex instanceof OutOfMemoryError) 
      memoryCache.clear(); 
     return null; 
    } 
} 

// decodes image and scales it to reduce memory consumption 
private Bitmap decodeFile(File f) { 
    try { 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     FileInputStream stream1 = new FileInputStream(f); 
     BitmapFactory.decodeStream(stream1, null, o); 
     stream1.close(); 

     final int REQUIRED_SIZE = 70; 
     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; 
     } 

     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize = scale; 
     FileInputStream stream2 = new FileInputStream(f); 
     Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2); 
     stream2.close(); 
     return bitmap; 
    } catch (FileNotFoundException e) { 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    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() { 
     try { 
      if (imageViewReused(photoToLoad)) 
       return; 
      Bitmap bmp = getBitmap(photoToLoad.url); 
      memoryCache.put(photoToLoad.url, bmp); 
      if (imageViewReused(photoToLoad)) 
       return; 
      BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad); 
      handler.post(bd); 
     } catch (Throwable th) { 
      th.printStackTrace(); 
     } 
    } 
} 

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(); 
} 
} 

ответ

2

Я бы рекомендовал что-то вроде fresco (который даже поддерживает от кучи запоминания изображения), Glide или Picasso, которые оптимизированы для Android изображения Загрузки библиотек. Я вообще против включения библиотеки для всего, но для загрузки изображений вы хотите быть быстрым и без ошибок. Один простой класс не может предложить это

+0

Спасибо, но любой из них имеет размер более одного мегабайта, в то время как мое приложение редко составляет 500 k. Кстати, моя работа с изображениями не так уж сложна. Просто загрузите миниатюры изображений и покажите их в виде списка, даже не нужно показывать их полный размер. Думаю, тот, который у меня есть, может быть оптимизирован. Также моя главная забота - это мои вопросы, связанные с механизмом ленивой загрузки. –