Используйте кэширование изображений LRU в сочетании с HTTPResponseCache для кэширования дисков и памяти

Первоначально цель состояла в том, чтобы использовать как кэш, так и диск. Это потребует реализации LRU-кеша и DiskLruCache. Однако, поскольку HTTPResponse кеш использует дисковое пространство, я решил использовать LRU кеш и сделать con.setUseCaches(true);

Проблема в том, что я не очень понимаю, что будет реализовано первым. Для кеша LRU и DiskLru это алгоритм:

т.е.

сначала проверьте кэш памяти для изображения

если есть изображение, верните его и обновите кэши

еще проверить кеш диска

если в кеше диска есть образ, верните его и обновите кеш

иначе скачайте образ из интернета, верните его и обновите кеш

Теперь с кодом ниже:

public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    private int inSampleSize = 0;

    private String imageUrl;

    private BaseAdapter adapter;

    private ImagesCache cache;

    private int desiredWidth, desiredHeight;

    private Bitmap image = null;

    private ImageView ivImageView;

    Context mContext;

    public DownloadImageTask(BaseAdapter adapter, int desiredWidth, int desiredHeight) {
        this.adapter = adapter;

        this.cache = ImagesCache.getInstance();

        this.desiredWidth = desiredWidth;

        this.desiredHeight = desiredHeight;
    }

    public DownloadImageTask(Context mContext, ImagesCache cache, ImageView ivImageView, int desireWidth, int desireHeight) {
        this.cache = cache;

        this.ivImageView = ivImageView;

        this.desiredHeight = desireHeight;

        this.desiredWidth = desireWidth;

        this.mContext = mContext;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        imageUrl = params[0];

        return getImage(imageUrl);
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
        if (result != null) {
            cache.addImageToWarehouse(imageUrl, result);
            if (ivImageView != null) {
                ivImageView.setImageBitmap(result);
            }
            else {
            }
            if (adapter != null) {
                adapter.notifyDataSetChanged();
            }
        }
                /*
        * IMPORTANT:
        * This enables your retrieval from the cache when working offline
        */
        /***
         * Force buffered operations to the filesystem. This ensures that responses
         * written to the cache will be available the next time the cache is opened,
         * even if this process is killed.
         */
        HttpResponseCache cache = HttpResponseCache.getInstalled();
        if(cache != null) {
            //the number of HTTP requests issued since this cache was created.
            Log.e("total num HTTP requests", String.valueOf(cache.getHitCount()));
            //the number of those requests that required network use.
            Log.e("num req network", String.valueOf(cache.getNetworkCount()));
            //the number of those requests whose responses were served by the cache.
            Log.e("num use cache", String.valueOf(cache.getHitCount()));
            //   If cache is present, flush it to the filesystem.
            //   Will be used when activity starts again.
            cache.flush();
            /***
             * Uninstalls the cache and releases any active resources. Stored contents
             * will remain on the filesystem.
             */
            //UNCOMMENTING THIS PRODUCES A java.lang.IllegalStateException: cache is closedtry {
              //  cache.close();
            //}
            //catch(IOException e){
              //  e.printStackTrace();
            //}
        }
    }

    private Bitmap getImage(String imageUrl) {
        if (cache.getImageFromWarehouse(imageUrl) == null) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            options.inSampleSize = inSampleSize;
            //installing the cache at application startup.
            try {
                HttpResponseCache cache = HttpResponseCache.getInstalled();
                if (cache == null) {
                    File httpCacheDir = new File(mContext.getCacheDir(), "http");
                    long HTTP_CACHE_SIZE_IN_BYTES = 1024 * 1024 * 1024; // 1GB
                    HttpResponseCache.install(httpCacheDir, HTTP_CACHE_SIZE_IN_BYTES);
                    //Log.e("Max DiskLRUCache Size", String.valueOf(DiskLruCache.getMaxSize());
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            try {
                int readTimeout = 300000;
                int connectTimeout = 300000;
                URL url = new URL(imageUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setUseCaches(true);
                connection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);
                connection.setConnectTimeout(connectTimeout);
                connection.setReadTimeout(readTimeout);
                InputStream stream = connection.getInputStream();
                image = BitmapFactory.decodeStream(stream, null, options);
                int imageWidth = options.outWidth;
                int imageHeight = options.outHeight;
                if (imageWidth > desiredWidth || imageHeight > desiredHeight) {
                    System.out.println("imageWidth:" + imageWidth + ", imageHeight:" + imageHeight);
                    inSampleSize = inSampleSize + 2;
                    getImage(imageUrl);
                }
                else {
                    options.inJustDecodeBounds = false;
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setUseCaches(true);
                    connection.addRequestProperty("Cache-Control", "only-if-cached");
                    connection.setConnectTimeout(connectTimeout);
                    connection.setReadTimeout(readTimeout);
                    stream = connection.getInputStream();
                    image = BitmapFactory.decodeStream(stream, null, options);
                    return image;
                }
            }
            catch (Exception e) {
                Log.e("getImage", e.toString());
            }
        }
        return image;
    }
}

Похоже, что в doInBackground() я сохраняю в HttpResponseCache, а в onPostExecute() я сохраняю то же изображение в LRUCache. Что я хотел бы сделать, это:

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

РЕДАКТИРОВАТЬ РЕФРЕЗОВЫЙ ВОПРОС

**

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

**

1 ответ

Решение

Если кто-то захочет повторно использовать любой из вышеприведенного кода, я бы взял только кеш ответов http и не использовал кеш LRU, особенно если вы кешируете ответ веб-службы, например, JSON,xml. Зачем?

Однажды я потерял 200 МБ памяти устройства из-за описанной выше реализации кэша LRU.

Преимущества HTTPResponseCache:

  • Кэширует ответы HTTP и HTTPS на файловую систему, чтобы их можно было повторно использовать, экономя время и пропускную способность.
  • HttpUrlConnection делает: Автоматическая обработка механизмов кэширования,
  • Ускоряет время отклика приложения с помощью HttpResponseCache
  • Он доступен с уровня API 1=>, он выдержал испытание временем и надежен

С другой стороны:

Хотя у LRUCache есть свои преимущества перед DiskLRUCache:

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

Это вывод...

Другие вопросы по тегам