Вопрос

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

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

Это было полезно?

Решение

Вот что я создал для хранения изображений, которые в данный момент отображает мое приложение.Обратите внимание, что используемый здесь объект «Журнал» — это моя собственная оболочка последнего класса журнала внутри 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();
    }
}

Другие советы

я сделал простая демонстрация ленивого списка (находится на 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

Я рекомендую инструмент с открытым исходным кодом Универсальный загрузчик изображений.Первоначально он основан на проекте Федора Власова. Ленивый список и с тех пор был значительно улучшен.

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

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

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

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

enter image description here

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

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

Год назад состоялось обсуждение SoftReferences в группах Google: ссылка на тему.В качестве решения слишком ранней сборки мусора предлагают возможность вручную задать размер кучи ВМ с помощью 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();
}

Пикассо

Используйте библиотеку Пикассо Джейка Уортона.(Идеальная библиотека загрузки изображений от разработчика 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, но также включает в себя подключаемые библиотеки утилит к проекту Google Volley или вместо библиотеки Square OkHttp.

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

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

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

Фреска от Facebook

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

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

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

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

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

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

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

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

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

Используйте Градл:

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

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

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

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

Используйте Градл:

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 заботится о загрузке и отображении изображений, поэтому вам не нужно.

Начало работы с Фреско

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

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

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

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

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

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

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

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

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

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

Это мой код:

@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;
}

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

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

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

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

Функции

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

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

enter image description here

Посмотри на Шаттербаг, облегченная SDWebImage от Applidium (хорошая библиотека для iOS), портированная на Android.Он поддерживает асинхронное кэширование, сохраняет неудачные URL-адреса, хорошо обрабатывает параллелизм и включает полезные подклассы.

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

Части дроида имеет Сборщик изображений для начала работы не требуется никакой настройки.

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

Клонировать ДроидЧастиГрамм для примера:

Enter image description here

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

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

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

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

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

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

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

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

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

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

Я также улучшил ImageLoader, реализовав синглтон в этом объекте.

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

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

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

Если вы хотите отображать макет Shimmer, как Facebook, для этого есть официальная библиотека Facebook. Facebook Мерцающий 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:0.1.0@aar'

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

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

Я могу порекомендовать другой способ, который работает как шарм:Андроид-запрос.

Вы можете скачать это БАНКА файл из здесь

AQuery androidAQuery = new AQuery(this);

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

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

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

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

URLImageViewHelper — замечательная библиотека, которая поможет вам в этом.

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

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

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

//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);
        }
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top