Ленивая загрузка изображений в ListView

Я использую ListView для отображения некоторых изображений и титров, связанных с этими изображениями. Я получаю изображения из Интернета. Есть ли способ ленивой загрузки изображений, поэтому, пока отображается текст, пользовательский интерфейс не заблокирован и изображения отображаются по мере их загрузки?

Общее количество изображений не фиксировано.

Вот что я создал для хранения изображений, которые в настоящее время отображается моим приложением. Обратите внимание, что используемый здесь объект «Журнал» – это моя настраиваемая shell вокруг конечного classа журнала внутри Android.

 package com.wilson.android.library; /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import java.io.IOException; public class DrawableManager { private final Map drawableMap; public DrawableManager() { drawableMap = new HashMap(); } public Drawable fetchDrawable(String urlString) { if (drawableMap.containsKey(urlString)) { return drawableMap.get(urlString); } Log.d(this.getClass().getSimpleName(), "image url:" + urlString); try { InputStream is = fetch(urlString); Drawable drawable = Drawable.createFromStream(is, "src"); if (drawable != null) { drawableMap.put(urlString, drawable); Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", " + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", " + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth()); } else { Log.w(this.getClass().getSimpleName(), "could not get thumbnail"); } return drawable; } catch (MalformedURLException e) { Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } catch (IOException e) { Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } } public void fetchDrawableOnThread(final String urlString, final ImageView imageView) { if (drawableMap.containsKey(urlString)) { imageView.setImageDrawable(drawableMap.get(urlString)); } final Handler handler = new Handler() { @Override public void handleMessage(Message message) { imageView.setImageDrawable((Drawable) message.obj); } }; Thread thread = new Thread() { @Override public void run() { //TODO : set imageView to a "pending" image Drawable drawable = fetchDrawable(urlString); Message message = handler.obtainMessage(1, drawable); handler.sendMessage(message); } }; thread.start(); } private InputStream fetch(String urlString) throws MalformedURLException, IOException { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet request = new HttpGet(urlString); HttpResponse response = httpClient.execute(request); return response.getEntity().getContent(); } } 

Я сделал простую демонстрацию ленивого списка (находящегося в GitHub) с изображениями. Это может быть полезно кому-то. Он загружает изображения в фоновый stream. Изображения кэшируются на SD-карте и в памяти. Реализация кэша очень проста и достаточно для демонстрации. Я декодирую изображения с помощью inSampleSize для уменьшения потребления памяти. Я также стараюсь правильно обрабатывать переработанные виды.

Alt текст

Я рекомендую инструмент с открытым исходным кодом Universal Image Loader . Первоначально он основан на проекте LazyList Федора Власова и с тех пор значительно улучшился.

  • Загрузка многопоточного изображения
  • Возможность широкой настройки конфигурации ImageLoader (исполнители streamов, downlaoder, декодер, кеш памяти и диска, параметры отображения изображения и другие)
  • Возможность кэширования изображений в памяти и / или в sysytem файла устройства (или SD-карты)
  • Возможность «прослушать» процесс загрузки
  • Возможность настройки каждого вызова изображения с отдельными параметрами
  • Поддержка виджета
  • Поддержка Android 2.0+

Многопоточность для производительности – учебник Гилла Дебунна.

Это из блога разработчиков Android. В предлагаемом коде используется:

  • AsyncTasks .
  • Трудный, ограниченный размер, FIFO cache .
  • Мягкий, легко garbage collect кеш.
  • Заполнитель , который можно использовать для загрузки.

введите описание изображения здесь

Обновление: обратите внимание, что этот ответ сейчас довольно неэффективен. Коллекционер мусора агрессивно действует на SoftReference и WeakReference, поэтому этот код НЕ подходит для новых приложений. (Вместо этого попробуйте библиотеки, такие как Universal Image Loader, предлагаемые в других ответах.)

Спасибо Джеймсу за код и Бао-Лонг за предложение использовать SoftReference. Я внедрил изменения SoftReference в коде Джеймса. К сожалению, SoftReferences заставил мои изображения слишком быстро собирать мусор. В моем случае это было прекрасно без материала SoftReference, потому что мой размер списка ограничен, а мои изображения малы.

Обсуждается год назад относительно SoftReferences для групп google: ссылка на stream . В качестве решения слишком ранней коллекции мусора они предполагают возможность ручной настройки размера кучи VM с помощью dalvik.system.VMRuntime.setMinimumHeapSize (), что для меня не очень привлекательно.

 public DrawableManager() { drawableMap = new HashMap>(); } public Drawable fetchDrawable(String urlString) { SoftReference drawableRef = drawableMap.get(urlString); if (drawableRef != null) { Drawable drawable = drawableRef.get(); if (drawable != null) return drawable; // Reference has expired so remove the key from drawableMap drawableMap.remove(urlString); } if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "image url:" + urlString); try { InputStream is = fetch(urlString); Drawable drawable = Drawable.createFromStream(is, "src"); drawableRef = new SoftReference(drawable); drawableMap.put(urlString, drawableRef); if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", " + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", " + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth()); return drawableRef.get(); } catch (MalformedURLException e) { if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } catch (IOException e) { if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } } public void fetchDrawableOnThread(final String urlString, final ImageView imageView) { SoftReference drawableRef = drawableMap.get(urlString); if (drawableRef != null) { Drawable drawable = drawableRef.get(); if (drawable != null) { imageView.setImageDrawable(drawableRef.get()); return; } // Reference has expired so remove the key from drawableMap drawableMap.remove(urlString); } final Handler handler = new Handler() { @Override public void handleMessage(Message message) { imageView.setImageDrawable((Drawable) message.obj); } }; Thread thread = new Thread() { @Override public void run() { //TODO : set imageView to a "pending" image Drawable drawable = fetchDrawable(urlString); Message message = handler.obtainMessage(1, drawable); handler.sendMessage(message); } }; thread.start(); } 

Пикассо

Используйте библиотеку Пикассо Джейка Уортона. (A Perfect ImageLoading Library формирует разработчика ActionBarSherlock)

Мощная библиотека загрузки и кэширования изображений для Android.

Изображения добавляют столь необходимый контекст и визуальное чутье для приложений Android. Picasso позволяет без проблем загружать изображения в приложение – часто в одной строке кода!

 Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); 

Многие распространенные ошибки загрузки изображений на Android автоматически обрабатываются Picasso:

Обработка утилиты ImageView и отмена загрузки в адаптере. Комплексные преобразования изображений с минимальным использованием памяти. Автоматическое кэширование памяти и дисков.

Библиотека Пикассо Джейка Уортона

скольжение

Glide – это быстрая и эффективная среда для управления носителями с открытым исходным кодом для Android, которая включает декодирование мультимедиа, память и кеширование дисков, а также объединение ресурсов в простой и удобный интерфейс.

Glide поддерживает выборку, декодирование и отображение видеоstreamов, изображений и анимированных GIF-файлов. Glide включает гибкий api, который позволяет разработчикам подключаться практически к любому сетевому стеклу. По умолчанию Glide использует собственный стек, основанный на HttpUrlConnection, но также включает в себя библиотеки утилиты, подключаемые к проекту Volley Google или библиотеке OkHttp Square.

 Glide.with(this).load("http://goo.gl/h8qOq7").into(imageView); 

Основное внимание Glide уделяется тому, чтобы прокручивать любой вид списка изображений как можно более гладко и быстро, но Glide также эффективен практически для любого случая, когда вам нужно выбирать, изменять размер и отображать удаленное изображение.

Библиотека загрузки изображений Glide

Фреска от Facebook

Fresco – мощная система для отображения изображений в приложениях Android.

Fresco заботится о загрузке и отображении изображений, поэтому вам не нужно. Он загрузит изображения из сети, локального хранилища или локальных ресурсов и покажет местозаполнитель до появления изображения. Он имеет два уровня кеша; один в памяти и другой во внутреннем хранилище.

Fresco Github

В Android 4.x и ниже Fresco помещает изображения в специальную область памяти Android. Это позволяет вашему приложению работать быстрее – и страдать от ужасного OutOfMemoryError гораздо реже.

Фресковая документация

Высокопроизводительный загрузчик – после изучения предложенных здесь методов я использовал решение Бена с некоторыми изменениями –

  1. Я понял, что работа с чертежами быстрее, чем с растровыми изображениями, поэтому вместо этого я использую drawables

  2. Использование SoftReference велико, но это слишком часто удаляет кешированное изображение, поэтому я добавил связанный список, содержащий ссылки на изображения, предотвращающие удаление изображения, до тех пор, пока он не достигнет предопределенного размера

  3. Чтобы открыть InputStream, я использовал java.net.URLConnection, который позволяет мне использовать веб-кеш (вам нужно сначала установить кеш ответа, но это еще одна история)

Мой код:

 import java.util.Map; import java.util.HashMap; import java.util.LinkedList; import java.util.Collections; import java.util.WeakHashMap; import java.lang.ref.SoftReference; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import android.graphics.drawable.Drawable; import android.widget.ImageView; import android.os.Handler; import android.os.Message; import java.io.InputStream; import java.net.MalformedURLException; import java.io.IOException; import java.net.URL; import java.net.URLConnection; public class DrawableBackgroundDownloader { private final Map> mCache = new HashMap>(); private final LinkedList  mChacheController = new LinkedList  (); private ExecutorService mThreadPool; private final Map mImageViews = Collections.synchronizedMap(new WeakHashMap()); public static int MAX_CACHE_SIZE = 80; public int THREAD_POOL_SIZE = 3; /** * Constructor */ public DrawableBackgroundDownloader() { mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); } /** * Clears all instance data and stops running threads */ public void Reset() { ExecutorService oldThreadPool = mThreadPool; mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); oldThreadPool.shutdownNow(); mChacheController.clear(); mCache.clear(); mImageViews.clear(); } public void loadDrawable(final String url, final ImageView imageView,Drawable placeholder) { mImageViews.put(imageView, url); Drawable drawable = getDrawableFromCache(url); // check in UI thread, so no concurrency issues if (drawable != null) { //Log.d(null, "Item loaded from mCache: " + url); imageView.setImageDrawable(drawable); } else { imageView.setImageDrawable(placeholder); queueJob(url, imageView, placeholder); } } private Drawable getDrawableFromCache(String url) { if (mCache.containsKey(url)) { return mCache.get(url).get(); } return null; } private synchronized void putDrawableInCache(String url,Drawable drawable) { int chacheControllerSize = mChacheController.size(); if (chacheControllerSize > MAX_CACHE_SIZE) mChacheController.subList(0, MAX_CACHE_SIZE/2).clear(); mChacheController.addLast(drawable); mCache.put(url, new SoftReference(drawable)); } private void queueJob(final String url, final ImageView imageView,final Drawable placeholder) { /* Create handler in UI thread. */ final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String tag = mImageViews.get(imageView); if (tag != null && tag.equals(url)) { if (imageView.isShown()) if (msg.obj != null) { imageView.setImageDrawable((Drawable) msg.obj); } else { imageView.setImageDrawable(placeholder); //Log.d(null, "fail " + url); } } } }; mThreadPool.submit(new Runnable() { @Override public void run() { final Drawable bmp = downloadDrawable(url); // if the view is not visible anymore, the image will be ready for next time in cache if (imageView.isShown()) { Message message = Message.obtain(); message.obj = bmp; //Log.d(null, "Item downloaded: " + url); handler.sendMessage(message); } } }); } private Drawable downloadDrawable(String url) { try { InputStream is = getInputStream(url); Drawable drawable = Drawable.createFromStream(is, url); putDrawableInCache(url,drawable); return drawable; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private InputStream getInputStream(String urlString) throws MalformedURLException, IOException { URL url = new URL(urlString); URLConnection connection; connection = url.openConnection(); connection.setUseCaches(true); connection.connect(); InputStream response = connection.getInputStream(); return response; } } 

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

1. Picasso позволяет без проблем загружать изображения в ваше приложение – часто в одной строке кода!

Использовать Gradle:

 implementation 'com.squareup.picasso:picasso:2.71828' 

Всего одна строка кода!

 Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView); 

2. Glide. Библиотека загрузки изображений и кеширования для Android ориентирована на плавную прокрутку

Использовать Gradle:

 repositories { mavenCentral() google() } dependencies { implementation 'com.github.bumptech.glide:glide:4.7.1' annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1' } 

// Для простого представления:

  Glide.with(this).load("http://i.imgur.com/DvpvklR.png").into(imageView); 

3. fresco – мощная система для отображения изображений в приложениях Android. Fresco берет на себя загрузку и отображение изображений, поэтому вам не нужно.

Начало работы с Fresco

Я написал учебное пособие, в котором объясняется, как делать ленивую загрузку изображений в виде списка. Я подробно расскажу о проблемах переработки и параллелизма. Я также использую фиксированный пул streamов, чтобы предотвратить нерестование множества streamов.

Ленивая загрузка изображений в учебнике Listview

Способ, которым я это делаю, – запустить stream для загрузки изображений в фоновом режиме и передать ему обратный вызов для каждого элемента списка. Когда изображение закончено, он вызывает обратный вызов, который обновляет представление для элемента списка.

Однако этот метод работает не очень хорошо, когда вы повторно просматриваете представления.

Я просто хочу добавить еще один хороший пример, XML-адаптеры . Поскольку он используется Google, и я также использую ту же логику, чтобы избежать ошибки OutOfMemory.

В основном этот ImageDownloader – ваш ответ (поскольку он охватывает большинство ваших требований). Некоторые из них также могут быть реализованы в этом.

Я использую NetworkImageView из новой библиотеки волейбола Android com.android.volley.toolbox.NetworkImageView и, похоже, работает очень хорошо. По-видимому, это та же точка зрения, которая используется в Google Play и других новых приложениях Google. Определенно стоит проверить.

  • Учебник по кэшу волейбола Google I / O 2013

  • События разработчиков Google

Это обычная проблема для Android, которая многими способами решена многими способами. На мой взгляд, лучшим решением, которое я видел, является относительно новая библиотека под названием Picasso . Вот основные моменты:

  • С открытым исходным кодом, но возглавил Jake Wharton из славы ActionBarSherlock .
  • Асинхронно загружать изображения из сети или приложений с помощью одной строки кода
  • Автоматическое обнаружение ListView
  • Автоматическое кэширование диска и памяти
  • Может выполнять пользовательские преобразования
  • Множество настраиваемых параметров
  • Супер простой API
  • Часто обновляется

Я думаю, что эта проблема очень популярна среди разработчиков Android, и есть много таких библиотек, которые претендуют на решение этой проблемы, но только некоторые из них, похоже, находятся на грани. AQuery – одна из таких библиотек, но она лучше, чем большинство из них во всех аспектах, и стоит попробовать.

Ну, время загрузки изображений из Интернета имеет множество решений. Вы также можете использовать библиотеку Android-Query . Это даст вам всю необходимую работу. Убедитесь, что вы хотите сделать и прочитайте страницу вики-библиотеки. И решите ограничение загрузки изображения.

Это мой код:

 @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.row, null); } ImageView imageview = (ImageView) v.findViewById(R.id.icon); AQuery aq = new AQuery(convertView); String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png"; aq.id(imageview).progress(this).image(imageUrl, true, true, 0, 0, new BitmapAjaxCallback() { @Override public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status) { iv.setImageBitmap(bm); } )); return v; } 

Это должно решить вашу ленивую проблему с загрузкой.

Посмотрите на Shutterbug , легкий USB-накопитель Appliedium SDWebImage (хорошая библиотека на iOS) для Android. Он поддерживает асинхронное кэширование, хранит неудачные URL-адреса, хорошо управляет параллелизмом и includeся полезные подclassы.

Запросы Pull (и отчеты об ошибках) также приветствуются!

Вы должны попробовать этот универсальный погрузчик. Я использую это после выполнения многих RnD при ленивой загрузке.

Универсальный загрузчик изображений

Особенности

  • Загрузка многопоточного изображения (асинхронная или синхронизация)
  • Широкая настройка конфигурации ImageLoader (исполнители streamов, загрузчик, декодер, память и кеш диска, параметры отображения изображения и т. Д.).
  • Множество параметров настройки для каждого вызова изображения (изображения заглушки, переключатель кеширования, варианты декодирования, обработка и отображение растровых изображений и т. Д.).
  • Кэширование изображений в памяти и / или на диске (файловая система устройства или SD-карта)
  • Прослушивание процесса загрузки (включая загрузку)

Поддержка Android 2.0+

введите описание изображения здесь

DroidParts имеет ImageFetcher , для которого требуется нулевая конфигурация.

  • Использует кэш с диском и памятью, используемым в последнее время (LRU).
  • Эффективно декодирует изображения.
  • Поддерживает изменение растровых изображений в фоновом streamе.
  • Имеет простой крест-затухание.
  • Has image loading progress callback.

Clone DroidPartsGram for an example:

Введите описание изображения здесь

Novoda also has a great lazy image loading library and many apps like Songkick, Podio, SecretDJ and ImageSearch use their library.

Their library is hosted here on Github and they have a pretty active issues tracker as well. Their project seems to be pretty active too, with over 300+ commits at the time of writing this reply.

Just a quick tip for someone who is in indecision regarding what library to use for lazy-loading images:

There are four basic ways.

  1. DIY => Not the best solution but for a few images and if you want to go without the hassle of using others libraries

  2. Volley’s Lazy Loading library => From guys at android. It is nice and everything but is poorly documented and hence is a problem to use.

  3. Picasso: A simple solution that just works, you can even specify the exact image size you want to bring in. It is very simple to use but might not be very “performant” for apps that has to deal with humongous amounts of images.

  4. UIL: The best way to lazy load images. You can cache images(you need permission of course), initialize the loader once, then have your work done. The most mature asynchronous image loading library I have ever seen so far.

Check my fork of LazyList . Basically, I improve the LazyList by delaying the call of the ImageView and create two methods:

  1. When you need to put something like “Loading image…”
  2. When you need to show the downloaded image.

I also improved the ImageLoader by implementing a singleton in this object.

All above code have their own worth but with my personal experience just give a try with Picasso.

Picasso is a library specifically for this purpose, in-fact it will manage cache and all other network operations automatically.You will have to add library in your project and just write a single line of code to load image from remote URL.

Please visit here : http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso–cms-22149

I can recommend a different way that works like a charm: Android Query.

You can download that JAR file from here

 AQuery androidAQuery = new AQuery(this); 

В качестве примера:

 androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW); 

It’s very fast and accurate, and using this you can find many more features like animation when loading, getting a bitmap (if needed), etc.

Give Aquery a try. It has amazingly simple methods to load and cache images asynchronously.

URLImageViewHelper is an amazing library that helps you to do that.

Use the glide library. It worked for me and will work for your code too.It works for both images as well as gifs too.

 ImageView imageView = (ImageView) findViewById(R.id.test_image); GlideDrawableImageViewTarget imagePreview = new GlideDrawableImageViewTarget(imageView); Glide .with(this) .load(url) .listener(new RequestListener() { @Override public boolean onException(Exception e, String model, Target target, boolean isFirstResource) { return false; } @Override public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) { return false; } }) .into(imagePreview); } 
 public class ImageDownloader { Map imageCache; public ImageDownloader() { imageCache = new HashMap(); } // download function public void download(String url, ImageView imageView) { if (cancelPotentialDownload(url, imageView)) { // Caching code right here String filename = String.valueOf(url.hashCode()); File f = new File(getCacheDirectory(imageView.getContext()), filename); // Is the bitmap in our memory cache? Bitmap bitmap = null; bitmap = (Bitmap) imageCache.get(f.getPath()); if (bitmap == null) { bitmap = BitmapFactory.decodeFile(f.getPath()); if (bitmap != null) { imageCache.put(f.getPath(), bitmap); } } // No? download it if (bitmap == null) { try { BitmapDownloaderTask task = new BitmapDownloaderTask( imageView); DownloadedDrawable downloadedDrawable = new DownloadedDrawable( task); imageView.setImageDrawable(downloadedDrawable); task.execute(url); } catch (Exception e) { Log.e("Error==>", e.toString()); } } else { // Yes? set the image imageView.setImageBitmap(bitmap); } } } // cancel a download (internal only) private static boolean cancelPotentialDownload(String url, ImageView imageView) { BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); if (bitmapDownloaderTask != null) { String bitmapUrl = bitmapDownloaderTask.url; if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { bitmapDownloaderTask.cancel(true); } else { // The same URL is already being downloaded. return false; } } return true; } // gets an existing download if one exists for the imageview private static BitmapDownloaderTask getBitmapDownloaderTask( ImageView imageView) { if (imageView != null) { Drawable drawable = imageView.getDrawable(); if (drawable instanceof DownloadedDrawable) { DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable; return downloadedDrawable.getBitmapDownloaderTask(); } } return null; } // our caching functions // Find the dir to save cached images private static File getCacheDirectory(Context context) { String sdState = android.os.Environment.getExternalStorageState(); File cacheDir; if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) { File sdDir = android.os.Environment.getExternalStorageDirectory(); // TODO : Change your diretcory here cacheDir = new File(sdDir, "data/ToDo/images"); } else cacheDir = context.getCacheDir(); if (!cacheDir.exists()) cacheDir.mkdirs(); return cacheDir; } private void writeFile(Bitmap bmp, File f) { FileOutputStream out = null; try { out = new FileOutputStream(f); bmp.compress(Bitmap.CompressFormat.PNG, 80, out); } catch (Exception e) { e.printStackTrace(); } finally { try { if (out != null) out.close(); } catch (Exception ex) { } } } // download asynctask public class BitmapDownloaderTask extends AsyncTask { private String url; private final WeakReference imageViewReference; public BitmapDownloaderTask(ImageView imageView) { imageViewReference = new WeakReference(imageView); } @Override // Actual download method, run in the task thread protected Bitmap doInBackground(String... params) { // params comes from the execute() call: params[0] is the url. url = (String) params[0]; return downloadBitmap(params[0]); } @Override // Once the image is downloaded, associates it to the imageView protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null) { ImageView imageView = imageViewReference.get(); BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); // Change bitmap only if this process is still associated with // it if (this == bitmapDownloaderTask) { imageView.setImageBitmap(bitmap); // cache the image String filename = String.valueOf(url.hashCode()); File f = new File( getCacheDirectory(imageView.getContext()), filename); imageCache.put(f.getPath(), bitmap); writeFile(bitmap, f); } } } } static class DownloadedDrawable extends ColorDrawable { private final WeakReference bitmapDownloaderTaskReference; public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) { super(Color.WHITE); bitmapDownloaderTaskReference = new WeakReference( bitmapDownloaderTask); } public BitmapDownloaderTask getBitmapDownloaderTask() { return bitmapDownloaderTaskReference.get(); } } // the actual download code static Bitmap downloadBitmap(String url) { HttpParams params = new BasicHttpParams(); params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); HttpClient client = new DefaultHttpClient(params); final HttpGet getRequest = new HttpGet(url); try { HttpResponse response = client.execute(getRequest); final int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); return null; } final HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inputStream = null; try { inputStream = entity.getContent(); final Bitmap bitmap = BitmapFactory .decodeStream(inputStream); return bitmap; } finally { if (inputStream != null) { inputStream.close(); } entity.consumeContent(); } } } catch (Exception e) { // Could provide a more explicit error message for IOException or // IllegalStateException getRequest.abort(); Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString()); } finally { if (client != null) { // client.close(); } } return null; } } 

I had this issue and implemented lruCache. I believe you need API 12 and above or use the compatiblity v4 library. lurCache is fast memory, but it also has a budget, so if you’re worried about that you can use a diskcache… It’s all described in Caching Bitmaps .

I’ll now provide my implementation which is a singleton I call from anywhere like this:

 //Where the first is a string and the other is a imageview to load. DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar); 

Here’s the ideal code to cache and then call the above in getView of an adapter when retrieving the web image:

 public class DownloadImageTask { private LruCache mMemoryCache; /* Create a singleton class to call this from multiple classes */ private static DownloadImageTask instance = null; public static DownloadImageTask getInstance() { if (instance == null) { instance = new DownloadImageTask(); } return instance; } //Lock the constructor from public instances private DownloadImageTask() { // Get max available VM memory, exceeding this amount will throw an // OutOfMemory exception. Stored in kilobytes as LruCache takes an // int in its constructor. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size will be measured in kilobytes rather than // number of items. return bitmap.getByteCount() / 1024; } }; } public void loadBitmap(String avatarURL, ImageView imageView) { final String imageKey = String.valueOf(avatarURL); final Bitmap bitmap = getBitmapFromMemCache(imageKey); if (bitmap != null) { imageView.setImageBitmap(bitmap); } else { imageView.setImageResource(R.drawable.ic_launcher); new DownloadImageTaskViaWeb(imageView).execute(avatarURL); } } private void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } private Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); } /* A background process that opens a http stream and decodes a web image. */ class DownloadImageTaskViaWeb extends AsyncTask { ImageView bmImage; public DownloadImageTaskViaWeb(ImageView bmImage) { this.bmImage = bmImage; } protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mIcon = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mIcon = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } addBitmapToMemoryCache(String.valueOf(urldisplay), mIcon); return mIcon; } /* After decoding we update the view on the main UI. */ protected void onPostExecute(Bitmap result) { bmImage.setImageBitmap(result); } } } 

You can try the Aquery Android library for lazy loading image and listview… The below code may help you….. download library from here .

 AQuery aq = new AQuery(mContext); aq.id(R.id.image1).image("http://data.whicdn.com/images/63995806/original.jpg"); 
  • Почему URL-адреса файлов начинаются с 3 косой черты?
  • Должен ли URL-адрес чувствителен к регистру?
  • .htaccess Rewrite to Force Trailing Slash в конце
  • URL без «http | https»
  • Проверьте, существует ли файл на удаленном сервере, используя его URL
  • отображать изображение из URL, полученного из ALAsset в iPhone
  • Код для декодирования / кодирования измененного URL-адреса base64
  • Обнаружение программно, установлено ли приложение на iPhone
  • Css Content, Attr и Url в том же предложении
  • Передайте локальный файл в URL в Java
  • java.net.URLEncoder.encode (String) устарел, что я должен использовать вместо этого?
  • Interesting Posts

    Как узнать, есть ли у вас фальшивая SD-карта

    Можно ли установить японский язык IME в Windows XP без компакт-диска?

    Ссылка на 2 разных версии log4net в одном решении

    Мне нужно включить и выключить питание ЖК-монитора, чтобы он оставался включенным

    Вызов метода Java без имени

    Как отформатировать указатель на функцию?

    Не удается получить бета-версию IIS Express 8 для запуска веб-сайта в виде 64-битного процесса

    invalid_grant пытается получить токен oAuth из google

    У вас есть надстройка для Firefox, например NoScript, но для файлов cookie (что позволяет сделать белый список во время просмотра в Интернете)?

    Как я могу манипулировать значимостью поиска полнотекстового поиска MySQL, чтобы сделать одно поле более «ценным», чем другое?

    Отключить сжатую память в Mac OS 10.9 Mavericks?

    Как использовать knockout.js с ASP.NET MVC ViewModels?

    Сбросить ассоциации файлов по умолчанию (idx открывает w / winRar)

    Добавление подсветки синтаксиса для раздела комментариев в Emacs

    Как получить последнюю запись для каждой группы в SQL

    Давайте будем гением компьютера.