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

голоса
1k

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

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

Задан 12/02/2009 в 16:59
источник пользователем
На других языках...                            


38 ответов

голоса
999

Вот что я создал для хранения изображений, мое приложение в настоящее время отображения. Обратите внимание, что «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();
    }
}
Ответил 18/02/2009 в 04:56
источник пользователем

голоса
979

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

Alt текст

Ответил 18/06/2010 в 09:04
источник пользователем

голоса
526

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

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

Ответил 19/12/2011 в 14:53
источник пользователем

голоса
146

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

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

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

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

Ответил 12/08/2010 в 12:07
источник пользователем

голоса
101

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

Благодаря Джеймсу для кода, и Бао-Long для предложения использования 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();
}
Ответил 05/05/2010 в 14:16
источник пользователем

голоса
83

Пикассо

Используйте Пикассо библиотека Jake Уортон. (A Perfect ImageLoading Библиотека есть разработчик ActionBarSherlock)

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

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

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

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

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

Библиотека Пикассо Jake Уортон

скольжение

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

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

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

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

Glide изображения Загрузка библиотеки

Фреска Facebook

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

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

Фреска Github

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

Fresco Документация

Ответил 04/04/2014 в 13:35
источник пользователем

голоса
77

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

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

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

  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;
}
}
Ответил 22/10/2011 в 17:44
источник пользователем

голоса
74

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

Ответил 28/12/2012 в 00:27
источник пользователем

голоса
54

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

Используйте Gradle:

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

Только одна строка кода!

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

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

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

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

2. Скольжение При загрузке изображений и библиотека кэширования для Android сосредоточены на гладкой прокрутки

Используйте Gradle:

repositories {
  mavenCentral() // jcenter() works as well because it pulls from Maven Central
}

dependencies {
  compile 'com.github.bumptech.glide:glide:3.7.0'
  compile 'com.android.support:support-v4:19.1.0'
}

// Для простого просмотра:

@Override public void onCreate(Bundle savedInstanceState) {
  ...
  ImageView imageView = (ImageView) findViewById(R.id.my_image_view);

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

// Для простого списка изображений:

 @Override public View getView(int position, View recycled, ViewGroup container) {
      final ImageView myImageView;
      if (recycled == null) {
        myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
      } else {
        myImageView = (ImageView) recycled;
      }

      String url = myUrls.get(position);

      Glide
        .with(myFragment)
        .load(url)
        .centerCrop()
        .placeholder(R.drawable.loading_spinner)
        .crossFade()
        .into(myImageView);

      return myImageView;
}
Ответил 22/05/2014 в 07:00
источник пользователем

голоса
49

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

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

Ответил 27/08/2011 в 13:54
источник пользователем

голоса
37

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

Этот метод не очень хорошо работает, когда вы рециркуляция взгляды однако.

Ответил 12/02/2009 в 21:07
источник пользователем

голоса
29

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

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

Ответил 14/12/2011 в 11:57
источник пользователем

голоса
26

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

Ответил 13/06/2013 в 16:17
источник пользователем

голоса
25

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

  • Открытый исходный код, но возглавил Jake Whartonиз ActionBarSherlock славы.
  • Асинхронная загрузка изображений из сети или приложения ресурсов с одной строки кода
  • Автоматическое ListViewобнаружение
  • Автоматический диск и кэширование памяти
  • Можно сделать пользовательские преобразования
  • Множество настраиваемых параметров
  • Супер простой API
  • Часто обновляемые
Ответил 16/10/2013 в 00:22
источник пользователем

голоса
22

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

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

Ответил 12/02/2013 в 08:10
источник пользователем

голоса
22

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

Ответил 11/12/2012 в 19:33
источник пользователем

голоса
18

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

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

Ответил 16/10/2012 в 13:43
источник пользователем

голоса
16

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

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

Особенности

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

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

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

Ответил 05/02/2015 в 12:45
источник пользователем

голоса
15

DroidParts имеет ImageFetcher , что требует нулевой конфигурации , чтобы начать работу.

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

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

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

Ответил 06/05/2013 в 10:48
источник пользователем

голоса
14

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

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

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

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

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

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

Ответил 03/08/2014 в 13:19
источник пользователем

голоса
14

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

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

Ответил 12/01/2013 в 12:00
источник пользователем

голоса
12

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

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

Я также улучшил ImageLoader путем внедрения одноплодной в этом объекте.

Ответил 13/02/2013 в 00:46
источник пользователем

голоса
9

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

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

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

Ответил 09/07/2015 в 16:16
источник пользователем

голоса
7

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

Ответил 27/01/2014 в 06:33
источник пользователем

голоса
7

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

Ответил 16/12/2013 в 14:04
источник пользователем

голоса
7

Я могу рекомендовать другой способ, который работает как шарм: 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);

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

Ответил 29/07/2013 в 08:06
источник пользователем

голоса
4

Используйте библиотеку глиссады. Он работал для меня и будет работать для вашего кода too.It работает на обоих изображениях, а также ГИФС тоже.

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);
}
Ответил 16/03/2017 в 10:11
источник пользователем

голоса
4

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

AQuery aq = new AQuery(mContext);
aq.id(R.id.image1).image("http://data.whicdn.com/images/63995806/original.jpg");
Ответил 03/09/2013 в 13:41
источник пользователем

голоса
4

Я имел эту проблему и реализовать lruCache. Я считаю , что вам нужно API 12 и выше , или использовать библиотеку v4 Совместимость. lurCache быстрая память, но она также имеет бюджет, так что если вы беспокоитесь о том, что вы можете использовать diskcache ... Это все описано в Caching Bitmaps .

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

//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);
        }
    }
}
Ответил 21/07/2013 в 18:51
источник пользователем

голоса
4
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;
 }
}
Ответил 18/07/2013 в 08:16
источник пользователем

голоса
3

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

Ответил 08/06/2014 в 10:04
источник пользователем

голоса
3

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

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

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


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

$.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);
        }
    })
);
Ответил 16/08/2013 в 21:06
источник пользователем

голоса
2

Если вы хотите отобразить Shimmer раскладку как Facebook есть официальная библиотека Facebok для этого. 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:0.1.0@aar'

Вот как это выглядит.Shimmer Android Скриншот

Ответил 26/02/2018 в 05:02
источник пользователем

голоса
2

Другой способ сделать это, через адаптер в потоке в вашем 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 массива. Кроме того, всегда проверяйте, что вы не утечка памяти, растровые изображения и часто вводимого коэффициента тяжел на память. Это до вас, чтобы оптимизировать свой код.

Ответил 21/06/2014 в 09:55
источник пользователем

голоса
1

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

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

  2. Внедрение механизма кэширования для хранения и извлечения изображения (использование LruCacheАндроида для кэширования)

Ответил 19/01/2016 в 09:59
источник пользователем

голоса
1

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

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){}
    }
}
Ответил 03/12/2015 в 09:01
источник пользователем

голоса
1

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

Ответил 03/12/2015 в 06:46
источник пользователем

голоса
-1

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

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

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

Ответил 14/06/2016 в 15:49
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more