Залповое кэширование изображений

Я пытаюсь понять кэширование изображений Volley. У меня есть фрагмент с gridview внутри него, который будет загружать около 12-30 изображений. Там изображения извлекаются с сервера, и я использую NetworkImageView для загрузки этих изображений.

Я могу отображать изображения в NetworkImageView, и все работает нормально. Но когда я переключаюсь с одного fragment на другой и возвращаюсь к предыдущему фрагменту, в LogCat, я вижу, что Volley снова пытается получить изображения.

Я читал, что Volley автоматически заботится о кэшировании изображений. Когда изображение кэшируется в первом fragment, почему он снова пытается получить изображение, когда я вернулся со второго на первое? Во-первых, это данные LogCat, показывающие запросы изображения Волей? или что-то другое...

Ниже мой код:

В onCreate()

queue = Volley.newRequestQueue(getActivity());
imageLoader = new ImageLoader(queue, new ImageLoader.ImageCache() {
    private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(
            10);

    public void putBitmap(String url, Bitmap bitmap) {
        mCache.put(url, bitmap);
    }

    public Bitmap getBitmap(String url) {
        return mCache.get(url);
    }
});

Logcat при первой загрузке фрагмента:

02-18 14:21:20.724: D/Volley(14713): [4944] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-11-57-29-pm.png 0x800c5bdc LOW 2> [lifetime=3782], [size=398563], [rc=200], [retryCount=0]
02-18 14:21:20.874: D/Volley(14713): [4943] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://xx.files.wordpress.com/2014/02/st-vincent.jpg 0x800c5bdc LOW 3> [lifetime=3941], [size=501475], [rc=200], [retryCount=0]
02-18 14:21:20.894: D/Volley(14713): [1] Request.finish: 4181 ms: [ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-11-57-29-pm.png 0x800c5bdc LOW 2
02-18 14:21:20.974: D/Volley(14713): [1] Request.finish: 4260 ms: [ ] http://xx.files.wordpress.com/2014/02/st-vincent.jpg 0x800c5bdc LOW 3
02-18 14:21:20.994: D/dalvikvm(14713): GC_FOR_ALLOC freed 1914K, 6% free 68371K/72184K, paused 11ms, total 11ms
02-18 14:21:20.994: I/dalvikvm-heap(14713): Grow heap (frag case) to 72.368MB for 5843106-byte allocation
02-18 14:21:21.014: D/dalvikvm(14713): GC_FOR_ALLOC freed 1K, 5% free 74076K/77892K, paused 15ms, total 15ms
02-18 14:21:21.074: D/Volley(14713): [1] Request.finish: 4336 ms: [ ] http://xx.files.wordpress.com/2014/02/underwater.gif 0x800c5bdc LOW 8
02-18 14:21:21.214: D/Volley(14713): [4945] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-4-24-04-pm.png 0x800c5bdc LOW 5> [lifetime=4155], [size=482380], [rc=200], [retryCount=0]
02-18 14:21:21.244: D/Volley(14713): [1] Request.finish: 4494 ms: [ ] http://xx.files.wordpress.com/2014/01/albarn-everyday-robots.jpg 0x800c5bdc LOW 9
02-18 14:21:21.274: D/Volley(14713): [1] Request.finish: 4551 ms: [ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-4-24-04-pm.png 0x800c5bdc LOW 5
02-18 14:21:21.994: D/Volley(14713): [1] Request.finish: 5244 ms: [ ] http://xx.files.wordpress.com/2014/02/macdemarco_baby.jpg 0x800c5bdc LOW 10
02-18 14:21:22.934: D/Volley(14713): [1] Request.finish: 6183 ms: [ ] http://xx.files.wordpress.com/2014/01/nenehcherry_lank01.jpg 0x800c5bdc LOW 11

Когда я возвращаюсь к тому же фрагменту во второй раз: только что посетил второй фрагмент и вернулся к первому фрагменту - между ними не так много промежутка..

02-18 14:27:46.164: D/dalvikvm(14713): GC_FOR_ALLOC freed 29047K, 26% free 91776K/122752K, paused 23ms, total 23ms
02-18 14:27:47.994: D/dalvikvm(14713): GC_FOR_ALLOC freed 2957K, 21% free 97010K/122752K, paused 20ms, total 20ms
02-18 14:27:48.274: D/Volley(14713): [1] Request.finish: 3244 ms: [ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-2-58-16-pm.png 0x800c5bdc LOW 6
02-18 14:27:48.294: D/dalvikvm(14713): GC_FOR_ALLOC freed 2007K, 21% free 97932K/122752K, paused 14ms, total 14ms
02-18 14:27:48.324: D/Volley(14713): [4956] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-11-57-29-pm.png 0x800c5bdc LOW 2> [lifetime=3272], [size=398563], [rc=200], [retryCount=0]
02-18 14:27:48.484: D/Volley(14713): [1] Request.finish: 3456 ms: [ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-11-57-29-pm.png 0x800c5bdc LOW 2
02-18 14:27:48.974: D/dalvikvm(14713): GC_FOR_ALLOC freed 1030K, 15% free 104815K/122752K, paused 56ms, total 56ms
02-18 14:27:49.054: D/Volley(14713): [1] Request.finish: 4022 ms: [ ] http://xx.files.wordpress.com/2014/02/screen-shot-2014-02-17-at-4-24-04-pm.png 0x800c5bdc LOW 5
02-18 14:27:49.314: D/Volley(14713): [1] Request.finish: 4276 ms: [ ] http://xx.files.wordpress.com/2014/01/albarn-everyday-robots.jpg 0x800c5bdc LOW 9
02-18 14:27:49.374: D/Volley(14713): [1] Request.finish: 4325 ms: [ ] http://xx.files.wordpress.com/2014/01/nenehcherry_lank01.jpg 0x800c5bdc LOW 11
02-18 14:27:49.404: D/Volley(14713): [1] Request.finish: 4355 ms: [ ] http://xx.files.wordpress.com/2014/02/macdemarco_baby.jpg 0x800c5bdc LOW 10
02-18 14:27:49.654: D/dalvikvm(14713): GC_FOR_ALLOC freed 1456K, 12% free 108705K/122752K, paused 27ms, total 27ms
02-18 14:27:49.734: D/Volley(14713): [1] Request.finish: 4691 ms: [ ] http://xx.files.wordpress.com/2014/02/underwater.gif 0x800c5bdc LOW 8
02-18 14:27:50.304: D/dalvikvm(14713): GC_FOR_ALLOC freed 11584K, 16% free 103314K/122752K, paused 47ms, total 47ms
02-18 14:27:50.334: D/Volley(14713): [1] Request.finish: 5281 ms: [ ] http://xx.files.wordpress.com/2014/02/echo-and-the-bunnymen.jpg 0x800c5bdc LOW 12

Как видно из ссылок, Volley обращается к тем же URL-адресам. Volley пытается получить изображения с сервера? или он просто показывает URL-адреса, которые он загружает из кеша?

Как сделать изображения кэша Volley? Если он не обрабатывает кэширование прямо сейчас, с моим кодом выше, что мне делать, чтобы добиться этого?

Я попытался изменить значение maxSize с 10 на 100*1024*1024 (100MB), но это не помешало Volley вывести те же значения.


person Vamsi Challa    schedule 18.02.2014    source источник


Ответы (7)


Залп не давал возможности кэширования напрямую. вы должны сделать свой собственный с помощью инструмента, предоставленного Volley. См. Кэширование сетевых изображений. Джейк Уортон написал о механизме кэширования с использованием Volley. Настройка залпа Джейка Уортона

person Tofeeq Ahmad    schedule 18.02.2014
comment
Хорошо.. Посмотрю. Просматривая другие вопросы, я нашел эту ссылку, stackoverflow.com/questions/16682595/ Могу ли я использовать этот способ для кэширования своих изображений? - person Vamsi Challa; 18.02.2014
comment
Может быть .. Но это кеширование объясняет кеширование памяти для дискового кеша, которое вам пришлось использовать для решения Jake. - person Tofeeq Ahmad; 18.02.2014
comment
Хорошо.. Спасибо за вашу помощь. Мы проверим решение Джейка и свяжемся с вами. Проголосовал. - person Vamsi Challa; 18.02.2014
comment
Будьте осторожны, чтобы не использовать кэш на основе диска, как тот, который написал Джейк Уортон, где Volley ожидает кэш памяти. - person Itai Hanski; 18.02.2014
comment
@ItaiHanski Может быть, в некоторых случаях это причиняет вред, но в большинстве случаев невозможно загрузить все изображение снова после запуска приложения. Важно, когда у вас много изображений - person Tofeeq Ahmad; 19.02.2014
comment
@Sameer Если вы предоставите дисковый кеш вместо кеша памяти, где ожидается кеш памяти, вы будете использовать 2 дисковых кеша, потому что у Volley уже есть дисковый кеш. Это плохо, потому что не только снизится производительность, но и вы будете занимать вдвое больше места на диске, которое будет содержать в основном дубликаты. - person Itai Hanski; 19.02.2014

По ссылке ниже вы можете увидеть продолжение моего вопроса о реализации кэширования изображений с помощью Volley с использованием DiskLruCache Джейка Уортона и VolleyImageCacheExample. Он работает так, как ожидалось, и изображения кэшируются. Спасибо за вашу помощь.

DiskLruCache Джейка Уортона — как реализовать с помощью Volley?

person Vamsi Challa    schedule 19.02.2014

Вы используете Volley как синглтон? Если это не так и вы не используете общий контекст для requestQueue, это не будет работать так, как вы ожидаете. Документация по этой части Volley особенно бесполезна (по крайней мере, с тех пор, как я использовал ее в последний раз). После правильной настройки он будет читать/записывать из кеша, как и следовало ожидать.

Вот проект GitHub с классом VolleySingleton, который вы можете использовать вместе с примерами: CypressNorth/Volley-Singleton

Вот сообщение в блоге, описывающее настройку более подробно: Настройка установить Android Google Volley ImageLoader для NetworkImageView

person Matt Mombrea    schedule 29.01.2015

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

Чтобы добавить Glide в ваше приложение:

Шаг 1) Обновите файл build.gradle

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

Шаг 2) Добавьте разрешение INTERNET в файл манифеста

<uses-permission android:name="android.permission.INTERNET" />

Шаг 3) Добавьте ImageView в свой макет

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageView"
    >
</ImageView>

Шаг 4) Использование скольжения в действии

    //Initialize ImageView
    ImageView imageView = (ImageView) findViewById(R.id.imageView);

    //Loading image from below url into imageView
   Glide.with(this)
        .load("IMAGE URL HERE")
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.imagenotfound)
        .override(200, 200);
        .centerCrop();
        .into(imageView);

Подробнее читайте в библиотеке Android Glide.

person macbee    schedule 14.06.2016

Вы можете проверить это, я включил механизм кэширования L1 и L2 для Volley.

Залп с кэшированием . Убедитесь, что в заголовке ответа включено управление кешем.

person sreekumar    schedule 02.04.2015

Самый простой способ кэширования изображений с помощью Volley, который я нашел, заключался в использовании RequestQueue с DiskBasedCache. Моя цель состояла в том, чтобы уменьшить пропускную способность, а не время загрузки. Это также снижает объем памяти.

 val cacheSizeInMegabytes = 5
 val cacheSizeInBytes = cacheSizeInMegabytes * 1024 * 1024
 val cacheDir = File(context.cacheDir, "volleyCache")
 val cache = DiskBasedCache(cacheDir, cacheSizeInBytes)

 val httpStack = HurlStack()
 val networkStack = BasicNetwork(httpStack)

 val queue = RequestQueue(cache, networkStack)
 queue.start()

Тогда просто используйте queue и убедитесь, что request.setShouldCache(true) есть (или нет).

person RhodanV5500    schedule 04.12.2018

Очень грубый способ, но он работает :)

package it.dataware.passaeprendi.app.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.LruCache;

import com.android.volley.VolleyLog;
import com.android.volley.toolbox.ImageLoader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

// https://stackoverflow.com/questions/14053338/save-bitmap-in-android-as-jpeg-in-external-storage-in-a-folder
// https://stackoverflow.com/questions/8710515/reading-an-image-file-into-bitmap-from-sdcard-why-am-i-getting-a-nullpointerexc

public class DiskBitmapCache implements ImageLoader.ImageCache {
private File   cacheDir;

// ...
private  static final String CACHE_PATH      = "dataware/passaeprendi/imagechache/";
private  static final String CACHE_FULL_PATH = Environment.getExternalStorageDirectory() + "/" + CACHE_PATH;
private  static final int    MAX_IMAGE_AGE   = 5; // in days

private  static final BitmapFactory.Options options = new BitmapFactory.Options();
static {
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
}

public DiskBitmapCache() {
    cacheDir = new File(CACHE_FULL_PATH);
    cacheDir.mkdirs();
}

private static  ImageLoader.ImageCache imageLoaderCache = new ImageLoader.ImageCache() {
    private final LruCache<String, Bitmap> mCache = new LruCache<>(30);

    public void putBitmap(String url, Bitmap bitmap) {
        mCache.put(url, bitmap);
    }
    public Bitmap getBitmap(String url) {
        return mCache.get(url);
    }
};

public Bitmap getBitmap(String url) {

    final String volleyFileName = getFilenameForKey(url);

    final Bitmap bitmapL1 = imageLoaderCache.getBitmap(volleyFileName);
    if (bitmapL1 != null) {
        // VolleyLog.d("taken from cache L1 :" + url + " -> " + volleyFileName + ".");
        return bitmapL1;
    }

    final File volleyCacheFile = new File(cacheDir, volleyFileName);

    if (!volleyCacheFile.exists()) {
        return null;
    }

    // =======================================
    // age check
    // =======================================

    long diff = new Date().getTime() - volleyCacheFile.lastModified();

    if (diff > MAX_IMAGE_AGE * 24 * 60 * 60 * 1000) {
        volleyCacheFile.delete();
        return null;
    }

    // =======================================
    // load from disk
    // =======================================

    Bitmap bitmap = BitmapFactory.decodeFile(volleyCacheFile.getAbsolutePath(), options);

    if (bitmap != null) {
        //     VolleyLog.d("taken from cache L2 :" + url + " -> " + volleyFileName + ".");
        imageLoaderCache.putBitmap(volleyFileName, bitmap);
    }

    // VolleyLog.d("taken from cache L2 :" + url + " -> " + volleyFileName + ".");
    return bitmap;
}

public void putBitmap(String url, Bitmap bitmap) {
    final String volleyFileName = getFilenameForKey(url);

    File volleyCacheFile = new File(cacheDir, volleyFileName);

    try {
        // ...
        FileOutputStream fos = null;
        volleyCacheFile.createNewFile();
        fos = new FileOutputStream(volleyCacheFile, false);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

// Volley creates a filename for the url with the following function, so we'll use the same function
// for translating the url back to said filename
private String getFilenameForKey(String key) {
    int firstHalfLength = key.length() / 2;

    // ..
    String  localFilename   = String.valueOf(key.substring(0, firstHalfLength)  .hashCode());
            localFilename  += String.valueOf(key.substring(firstHalfLength)     .hashCode());
            localFilename  += ".jpg";

    return localFilename;
}
}    

Надеюсь кому-то поможет.

person Stefano Carfagna    schedule 07.07.2020