it-swarm.com.ru

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

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

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

1846
lostInTransit

Вот то, что я создал для хранения изображений, которые мое приложение отображает в данный момент. Обратите внимание, что используемый здесь объект "Log" - это моя специальная оболочка для заключительного класса Log внутри 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<String, Drawable> drawableMap;

    public DrawableManager() {
        drawableMap = new HashMap<String, Drawable>();
    }

    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();
    }
}
1058
James A Wilson

Я сделал простая демонстрация ленивого списка (находится на GitHub) с изображениями.

Основное использование

ImageLoader imageLoader=new ImageLoader(context); ...
imageLoader.DisplayImage(url, imageView); 

Не забудьте добавить следующие разрешения в ваш AndroidManifest.xml:

 <uses-permission Android:name="Android.permission.INTERNET"/>
 <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/> Please

создайте только один экземпляр ImageLoader и повторно используйте его в своем приложении. Таким образом, кэширование изображений будет намного более эффективным.

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

Alt text

1011
Fedor

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

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

546
nostra13

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

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

  • AsyncTasks.
  • Жесткий, ограниченный размер, FIFO cache.
  • Мягкий, легко garbage collect- ed кеш.
  • заполнитель Drawable во время загрузки.

enter image description here

154
Thomas Ahle

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

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

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

public DrawableManager() {
    drawableMap = new HashMap<String, SoftReference<Drawable>>();
}

public Drawable fetchDrawable(String urlString) {
    SoftReference<Drawable> 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>(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<Drawable> 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();
}
105
TalkLittle

Пикассо

Используйте Библиотеку Пикассо Джейка Уортона. (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 поддерживает выборку, декодирование и отображение видеоизображений, изображений и анимированных 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 заботится о загрузке и отображении изображений, поэтому вам не нужно этого делать. Он будет загружать изображения из сети, локального хранилища или локальных ресурсов и отображать заполнитель до тех пор, пока изображение не будет получено. Имеет два уровня кеша; один в памяти и другой во внутренней памяти.

Фреска Гитхуб

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

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

93
Ashwin S Ashok

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

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

  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<String, SoftReference<Drawable>> mCache = new HashMap<String, SoftReference<Drawable>>();   
private final LinkedList <Drawable> mChacheController = new LinkedList <Drawable> ();
private ExecutorService mThreadPool;  
private final Map<ImageView, String> mImageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());  

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>(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;
}
}
79
Asaf Pinhassi

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

77
toobsco42

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

Используйте 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. фреска это мощная система для отображения изображений в приложениях Android. Фреска позаботится о загрузке и отображении изображений, так что вам это не нужно.

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

63
chiragkyada

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

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

51
Ben Ruijl

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

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

39
jasonhudgins

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

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

31
Arslan

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

28
droidment

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

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

Ну, время загрузки изображения из Интернета имеет много решений. Вы также можете использовать библиотеку 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;
}

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

25
Rahul Rawat

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

24
Ritesh Kumar Dubey

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

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

Особенности

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

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

enter image description here

21
Girish Patel

Взгляните на Shutterbug , облегченный порт Appwidium SDWebImage (библиотека Nice на iOS) для Android. Он поддерживает асинхронное кэширование, сохраняет ошибочные URL-адреса, хорошо обрабатывает параллелизм и содержит полезные подклассы.

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

20
PatrickNLT

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

  • Использует диск и в памяти наименьшее количество недавно использованных (LRU) кеш.
  • Эффективно декодирует изображения.
  • Поддерживает изменение растровых изображений в фоновом потоке.
  • Имеет простое затухание.
  • Имеет обратный вызов процесса загрузки изображения.

Клон DroidPartsGram для примера:

Enter image description here

16
yanchenko

Просто быстрый совет для тех, кто не решен, какую библиотеку использовать для лениво загружаемых изображений:

Есть четыре основных способа.

  1. DIY => Не лучшее решение, но для нескольких изображений и если вы хотите обойтись без использования других библиотек

  2. Volley's Lazy Загрузка библиотеки => От парней на Android. Это хорошо и все, но плохо документировано и, следовательно, является проблемой для использования.

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

  4. UIL: лучший способ ленивой загрузки изображений. Вы можете кэшировать изображения (вам, конечно, нужно разрешение), один раз инициализировать загрузчик, а затем выполнить свою работу. Самая зрелая библиотека асинхронной загрузки изображений, которую я когда-либо видел.

16
Bijay Koirala

У Novoda также есть отличная библиотека отложенной загрузки изображений , и многие приложения, такие как Songkick, Podio, SecretDJ и ImageSearch, используют свою библиотеку.

Их библиотека размещена здесь на Github, и у них есть довольно активная система отслеживания проблем . Их проект, кажется, тоже довольно активен: более 300 коммитов на момент написания этого ответа.

15
Soham

Проверьте мой форк LazyList . По сути, я улучшаю LazyList, задерживая вызов ImageView и создаю два метода:

  1. Когда вам нужно поставить что-то вроде "Загрузка изображения ..."
  2. Когда вам нужно показать загруженное изображение.

Я также улучшил ImageLoader, добавив singleton в этот объект.

13
Nicolas Jafelle

Весь приведенный выше код имеет свою ценность, но с моим личным опытом просто попробуйте с Пикассо.

Picasso - это библиотека, специально предназначенная для этой цели, фактически она будет автоматически управлять кэшем и всеми другими сетевыми операциями. Вам нужно будет добавить библиотеку в свой проект и просто написать одну строку кода для загрузки изображения с удаленного URL.

Пожалуйста, посетите здесь: http://code.tutsplus.com/tutorials/Android-sdk-working-with-picasso--cms-22149

11
Akbar

Если вы хотите отобразить макет Shimmer, такой как Facebook, для этого есть официальная библиотека Facebook. FaceBook Shimmer Android

Это обо всем позаботится, вам просто нужно поместить желаемый код дизайна в виде мерцающей рамки. Вот пример кода.

<com.facebook.shimmer.ShimmerFrameLayout
     Android:id=“@+id/shimmer_view_container”
     Android:layout_width=“wrap_content”
     Android:layout_height="wrap_content"
     shimmer:duration="1000">

 <here will be your content to display />

</com.facebook.shimmer.ShimmerFrameLayout>

И вот код Java для него.

ShimmerFrameLayout shimmerContainer = (ShimmerFrameLayout) findViewById(R.id.shimmer_view_container);
shimmerContainer.startShimmerAnimation();

Добавьте эту зависимость в ваш файл Gradle.

implementation 'com.facebook.shimmer:shimmer:[email protected]'

Вот как это выглядит . Shimmer Android screenshot

10
Zankrut Parmar

Используйте библиотеку скольжения. Это сработало для меня и будет работать для вашего кода. Это работает как для изображений, так и для GIF-файлов.

ImageView imageView = (ImageView) findViewById(R.id.test_image); 
    GlideDrawableImageViewTarget imagePreview = new GlideDrawableImageViewTarget(imageView);
    Glide
            .with(this)
            .load(url)
            .listener(new RequestListener<String, GlideDrawable>() {
                @Override
                public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {                       
                    return false;
                }

                @Override
                public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    return false;
                }
            })
            .into(imagePreview);
}
9
Saket Kumar

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

7
user2779311

Я могу порекомендовать другой способ, который работает как брелок: Android Запрос.

Вы можете скачать этот файл JAR из здесь

AQuery androidAQuery = new AQuery(this);

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

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

Это очень быстро и точно, и с его помощью вы можете найти много других функций, таких как анимация при загрузке, получение растрового изображения (при необходимости) и т.д.

7
Pratik Dasa

RLImageViewHelper - это удивительная библиотека, которая поможет вам сделать это.

7
DiegoAlt
public class ImageDownloader {

Map<String, Bitmap> imageCache;

public ImageDownloader() {
    imageCache = new HashMap<String, Bitmap>();

}

// 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<String, Void, Bitmap> {
    private String url;
    private final WeakReference<ImageView> imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(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<BitmapDownloaderTask> bitmapDownloaderTaskReference;

    public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
        super(Color.WHITE);
        bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
                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;
 }
}
4
Nikhil Gupta

Другой способ сделать это через ваш адаптер в потоке в вашем методе getView ():

Thread pics_thread = new Thread(new Runnable() {
    @Override
    public void run() {
        Bitmap bitmap = getPicture(url);
        if(bitmap != null) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    holder.imageview.setImageBitmap(bitmap);            
                    adapter.notifyDataSetChanged();
                }                       
            });             
        }       
    }                       
});

pics_thread.start();

конечно, вы всегда должны кэшировать свои изображения, чтобы избежать лишних операций, вы можете поместить свои изображения в массив HashMap, проверить, существует ли изображение в массиве, если нет, продолжить работу с потоком или загрузить изображение из вашего массива HashMap. Также всегда проверяйте, что у вас нет утечек памяти, растровые изображения и графические объекты часто сильно загружают память. Это зависит от вас, чтобы оптимизировать ваш код.

4
Samet

У меня была эта проблема и я реализовал lruCache. Я считаю, что вам нужно API 12 и выше или использовать библиотеку v4 совместимости. lurCache - это быстрая память, но она также имеет бюджет, поэтому, если вы беспокоитесь о том, что вы можете использовать дисковый кэш ... Все это описано в Кэширование растровых изображений.

Теперь я предоставлю свою реализацию singleton Я звоню из любого места, например так:

//Where the first is a string and the other is a imageview to load.

DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar);

Вот идеальный код для кеширования и последующего вызова вышеуказанного в getView адаптера при извлечении веб-изображения:

public class DownloadImageTask {

    private LruCache<String, Bitmap> 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<String, Bitmap>(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<String, Void, Bitmap> {
        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);
        }
    }
}
4
j2emanue

Вы можете попробовать Aquery Android библиотеку для отложенной загрузки изображения и просмотра списка ... Приведенный ниже код может помочь вам ..... скачать библиотеку отсюда .

AQuery aq = new AQuery(mContext);
aq.id(R.id.image1).image("http://data.whicdn.com/images/63995806/original.jpg");
4
Chirag Ghori

используйте приведенный ниже класс для загрузки и загрузки изображений в listview. Он кэширует каждое изображение после загрузки. Также загружает изображения и ленивая загрузка.

package com.fudiyoxpress.images;

import Java.io.File;
import Java.io.FileInputStream;
import Java.io.FileNotFoundException;
import Java.io.FileOutputStream;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.OutputStream;
import Java.net.HttpURLConnection;
import Java.net.URL;
import Java.util.Collections;
import Java.util.Map;
import Java.util.WeakHashMap;
import Java.util.concurrent.ExecutorService;
import Java.util.concurrent.Executors;

import Android.content.Context;
import Android.graphics.Bitmap;
import Android.graphics.BitmapFactory;
import Android.os.Handler;
import Android.widget.ImageView;

import com.fudiyoxpress.R;
import com.fudiyoxpress.config.Config;
import com.fudiyoxpress.Twitter.ScaleBitmap;

public class ImageLoader {

    // Initialize MemoryCache
    MemoryCache memoryCache = new MemoryCache();

    FileCache fileCache;

    Context C;

    // Create Map (collection) to store image and image url in key value pair
    private Map<ImageView, String> imageViews = Collections
            .synchronizedMap(new WeakHashMap<ImageView, String>());
    ExecutorService executorService;

    // handler to display images in UI thread
    Handler handler = new Handler();

    public ImageLoader(Context context) {

        C = context;
        fileCache = new FileCache(context);

        // Creates a thread pool that reuses a fixed number of
        // threads operating off a shared unbounded queue.
        executorService = Executors.newFixedThreadPool(5);

    }

    // default image show in list (Before online image download)
    final int stub_id = R.drawable.restlogoplaceholder;

    public void DisplayImage(String url, ImageView imageView, Context context,
            boolean header_flag) {

        Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.restlogoplaceholder);
        header_flag = false;
        // Store image and url in Map
        imageViews.put(imageView, url);

        // Check image is stored in MemoryCache Map or not (see
        // MemoryCache.Java)
        Bitmap bitmap = memoryCache.get(url);

        if (bitmap != null) {
            // if image is stored in MemoryCache Map then
            // Show image in listview row
            Bitmap b = ScaleBitmap
                    .getScaledBitmap(context, bitmap, header_flag);
            imageView.setImageBitmap(b);

        } else {
            // queue Photo to download from url
            queuePhoto(url, imageView, header_flag);

            // Before downloading image show default image
            imageView.setImageBitmap(ScaleBitmap.getScaledBitmap(context,
                    largeIcon, header_flag));

        }
    }



    private void queuePhoto(String url, ImageView imageView, boolean header_flag) {
        // Store image and url in PhotoToLoad object
        PhotoToLoad p = new PhotoToLoad(url, imageView, header_flag);

        // pass PhotoToLoad object to PhotosLoader runnable class
        // and submit PhotosLoader runnable to executers to run runnable
        // Submits a PhotosLoader runnable task for execution

        executorService.submit(new PhotosLoader(p));
    }

    // Task for the queue
    private class PhotoToLoad {
        public String url;
        public ImageView imageView;
        public boolean b;

        public PhotoToLoad(String u, ImageView i, boolean header_flag) {
            url = u;
            imageView = i;
            b = header_flag;
        }
    }

    class PhotosLoader implements Runnable {
        PhotoToLoad photoToLoad;

        PhotosLoader(PhotoToLoad photoToLoad) {
            this.photoToLoad = photoToLoad;
        }

        @Override
        public void run() {
            try {
                // Check if image already downloaded
                if (imageViewReused(photoToLoad))
                    return;
                // download image from web url
                Bitmap bmp = getBitmap(photoToLoad.url);

                // set image data in Memory Cache
                memoryCache.put(photoToLoad.url, bmp);

                if (imageViewReused(photoToLoad))
                    return;

                // Get bitmap to display
                BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);

                // Causes the Runnable bd (BitmapDisplayer) to be added to the
                // message queue.
                // The runnable will be run on the thread to which this handler
                // is attached.
                // BitmapDisplayer run method will call
                handler.post(bd);

            } catch (Throwable th) {
                // th.printStackTrace();
            }
        }
    }

    private Bitmap getBitmap(String url) {
        File f = fileCache.getFile(url);

        // from SD cache
        // CHECK : if trying to decode file which not exist in cache return null
        Bitmap b = decodeFile(f);
        if (b != null)
            return b;

        // Download image file from web
        try {

            // // download the image
            Bitmap bitmap = null;

            URL imageURL = null;
            try {

                imageURL = new URL(Config.WEB_URL + "/ServeBlob?id=" + url);

                HttpURLConnection connection = (HttpURLConnection) imageURL
                        .openConnection();
                connection.setDoInput(true);
                connection.connect();
                // if(!(new File(imageURL.toString())).exists())
                // {
                // imageURL=new URL("");
                // }
                InputStream inputStream = connection.getInputStream();

                // Constructs a new FileOutputStream that writes to
                // file
                // if file not exist then it will create file
                OutputStream os = new FileOutputStream(f);

                // See Utils class CopyStream method
                // It will each pixel from input stream and
                // write pixels to output stream (file)
                Utils.CopyStream(inputStream, os);

                os.close();

                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 8;

                bitmap = BitmapFactory.decodeStream(inputStream, null, options);

            } catch (IOException e) {

                // e.printStackTrace();
            }

            // Now file created and going to resize file with defined height
            // Decodes image and scales it to reduce memory consumption
            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 {

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            FileInputStream stream1 = new FileInputStream(f);
            BitmapFactory.decodeStream(stream1, null, o);
            stream1.close();

            // Find the correct scale value. It should be the power of 2.

            // Set width/height of recreated image
            final int REQUIRED_SIZE = 85;

            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 current scale values
            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;
    }

    boolean imageViewReused(PhotoToLoad photoToLoad) {

        String tag = imageViews.get(photoToLoad.imageView);
        // Check url is already exist in imageViews MAP
        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;

            // Show bitmap on UI
            if (bitmap != null) {
                photoToLoad.imageView.setImageBitmap(ScaleBitmap
                        .getScaledBitmap(C, bitmap, photoToLoad.b));
            } else {

            }
            // photoToLoad.imageView.setImageResource(stub_id);

        }
    }

    public void clearCache() {
        // Clear cache directory downloaded images and stored data in maps
        memoryCache.clear();
        fileCache.clear();
    }

}




package com.fudiyoxpress.images;

import Java.util.Collections;
import Java.util.Iterator;
import Java.util.LinkedHashMap;
import Java.util.Map;
import Java.util.Map.Entry;
import Android.graphics.Bitmap;
import Android.util.Log;

public class MemoryCache {

    private static final String TAG = "MemoryCache";

    //Last argument true for LRU ordering
    private Map<String, Bitmap> cache = Collections.synchronizedMap(
            new LinkedHashMap<String, Bitmap>(10,1.5f,true));

   //current allocated size
    private long size=0; 

    //max memory cache folder used to download images in bytes
    private long limit = 1000000; 

    public MemoryCache(){

        //use 25% of available heap size
        setLimit(Runtime.getRuntime().maxMemory()/4);
    }

    public void setLimit(long new_limit){

        limit=new_limit;
        Log.i(TAG, "MemoryCache will use up to "+limit/1024./1024.+"MB");
    }

    public Bitmap get(String id){
        try{
            if(!cache.containsKey(id))
                return null;
            //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 
            return cache.get(id);
        }catch(NullPointerException ex){
            ex.printStackTrace();
            return null;
        }
    }

    public void put(String id, Bitmap bitmap){
        try{
            if(cache.containsKey(id))
                size-=getSizeInBytes(cache.get(id));
            cache.put(id, bitmap);
            size+=getSizeInBytes(bitmap);
            checkSize();
        }catch(Throwable th){
            th.printStackTrace();
        }
    }

    private void checkSize() {
        Log.i(TAG, "cache size="+size+" length="+cache.size());
        if(size>limit){
            Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iterated  
            while(iter.hasNext()){
                Entry<String, Bitmap> entry=iter.next();
                size-=getSizeInBytes(entry.getValue());
                iter.remove();
                if(size<=limit)
                    break;
            }
            Log.i(TAG, "Clean cache. New size "+cache.size());
        }
    }

    public void clear() {
        try{
            //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 
            cache.clear();
            size=0;
        }catch(NullPointerException ex){
            ex.printStackTrace();
        }
    }

    long getSizeInBytes(Bitmap bitmap) {
        if(bitmap==null)
            return 0;
        return bitmap.getRowBytes() * bitmap.getHeight();
    }
}




package com.fudiyoxpress.images;

import Java.io.InputStream;
import Java.io.OutputStream;

public class Utils {
    public static void CopyStream(InputStream is, OutputStream os)
    {
        final int buffer_size=1024;
        try
        {

            byte[] bytes=new byte[buffer_size];
            for(;;)
            {
              //Read byte from input stream

              int count=is.read(bytes, 0, buffer_size);
              if(count==-1)
                  break;

              //Write byte from output stream
              os.write(bytes, 0, count);
            }
        }
        catch(Exception ex){}
    }
}
3
Jotiram Chavan

Я использую droidQuery . Существует два механизма загрузки изображения из URL. Первый (сокращение) это просто:

$.with(myView).image(url);

Это можно очень легко добавить в метод ArrayAdapter's getView(...).


Длинный метод даст намного больший контроль и имеет опции, которые даже не обсуждались здесь (такие как кэширование и обратные вызовы), но здесь можно найти базовую реализацию, которая определяет размер вывода как 200px x 200px:

$.ajax(new AjaxOptions().url(url)
    .type("GET")
    .dataType("image")
    .imageWidth(200).imageHeight(200)
    .success(new Function() {
        @Override
        public void invoke($ droidQuery, Object... params) {
            myImageView.setImageBitmap((Bitmap) params[0]);
        }
    })
    .error(new Function() {
        @Override
        public void invoke($ droidQuery, Object... params) {
            AjaxError e = (AjaxError) params[0];
            Log.e("$", "Error " + e.status + ": " + e.error);
        }
    })
);
3
Phil

В некоторых ответах уже упоминалось использование различных библиотек изображений, таких как Universal Image Loader, androidimageloader и т.д. Это старый вопрос, но для тех, кто все еще ищет что-то подобное, есть несколько таких библиотек для загрузки/кэширования изображений.

3
redGREENblue

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

  1. Реализуйте код для загрузки изображения с URL

  2. Реализовать механизм кэширования для хранения и извлечения изображения (используйте LruCache из Android для кэширования)

2
BalaramNayak

Я нашел Glide как лучший вариант, чем Picasso. Я использовал Picasso для загрузки около 32 изображений размером около 200-500KB каждое, и я всегда получал OOM. Но Glide решил все мои проблемы OOM.

2
Sanjeet A

Вы можете использовать AsyncImageView GreenDroid. Просто позвоните setUrl, и я думаю, что это может помочь сделать то, что вы хотите сделать, и сослаться на эту ссылку, приведенную ниже:

ссылка на asyncimageview для GreenDroid

0
Imran

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

За исключением загрузки данных видимого элемента, вам может потребоваться загрузить данные видимого приближения элемента

Пример: предположим, что видимым элементом списка является [6,7,8,9,10], может потребоваться загрузить [6,7,8,9,10] И предварительно загрузить элемент [1, 2, 3, 4 , 5] и [11, 12, 13, 14, 15], потому что пользователь, вероятно, прокручивает до или после страницы

0
Yessy