Android Volley не кэширует изображения

Я использовал это учебник для отображения и кэширования изображения в сетке с использованием Volley. при подключении интернета все работает нормально .но после отключения изображение не показывает.кажется Залп не кеширует изображения. проблема в том, что нет полной документации о кэшировании изображений с помощью Volley. Вот мой код:

xml:

<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/container_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar" />
    </LinearLayout>


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#F4F4F6"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".Content_Gallery_Activity">

        <TextView
            android:id="@+id/text_gallery_title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <RelativeLayout
            android:id="@+id/relative_gallery"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_below="@+id/text_gallery_title"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginTop="10dp"
            android:background="@drawable/rect_lst_tree"
            android:paddingLeft="10dp"
            android:paddingRight="10dp" >

            <com.beardedhen.androidbootstrap.AwesomeTextView
                android:id="@+id/font_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_toLeftOf="@+id/tv_date_gallery"
                app:bootstrapBrand="info"
                app:fontAwesomeIcon="fa_clock_o"
                >
            </com.beardedhen.androidbootstrap.AwesomeTextView>

            <TextView
                android:id="@+id/tv_date_gallery"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginLeft="5dp"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:textColor="#1B131B"
                android:textSize="13dp" >
            </TextView>

            <TextView
                android:id="@+id/text_image_count"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_toRightOf="@+id/gallery_thumb"
                android:text="Small"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:textColor="#F01435"
                android:textSize="12dp" />

            <ir.whc.news.views.CircularNetworkImageView
                android:id="@+id/gallery_thumb"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_centerVertical="true"
                >
            </ir.whc.news.views.CircularNetworkImageView>
        </RelativeLayout>

        <GridView
            android:id="@+id/gridView1"
            android:layout_width="match_parent"
            android:layout_height="fill_parent"
            android:layout_below="@+id/relative_gallery"
            android:columnWidth="100dp"
            android:horizontalSpacing="1dp"
            android:numColumns="auto_fit"
            android:paddingTop="10dp"
            android:stretchMode="spacingWidthUniform"
            android:verticalSpacing="8dp" >
        </GridView>

    </RelativeLayout>
</LinearLayout>


<fragment
    android:id="@+id/fragment_navigation_drawer"
    android:name="ir.whc.news.activity.FragmentDrawer"
    android:layout_width="@dimen/nav_drawer_width"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:layout="@layout/fragment_navigation_drawer"
    tools:layout="@layout/fragment_navigation_drawer" />

Actitvity:

    grd.setAdapter(new MyImageAdapter(galleryItem.get_images()));
        grd.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(ContentGalleryActivity.this, DisplayImageActivity.class);
                intent.putExtra("largimage_url", galleryItem.get_images().get(position).get_largimage_path());
                startActivity(intent);
            }
        });

адаптер:

    class MyImageAdapter extends BaseAdapter {

        ArrayList<ImageItem> imageItems;

        public MyImageAdapter(ArrayList<ImageItem> imageItems)
        {
            this.imageItems=imageItems;
        }

        @Override
        public int getCount() {
            return imageItems.size();
        }

        @Override
        public Object getItem(int position) {
            return imageItems.get(position);
        }

        @Override
        public long getItemId(int position) {
            return imageItems.get(position).get_id();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            View view = convertView;
            final ViewHolder gridViewImageHolder;
//            check to see if we have a view
            if (view == null) {
                view = getLayoutInflater().inflate(R.layout.grid_image_item, parent, false);
                gridViewImageHolder = new ViewHolder();
                gridViewImageHolder.imageView = (ImageView) view.findViewById(R.id.image_grid_networkImageView);
                view.setTag(gridViewImageHolder);
            } else {
                gridViewImageHolder = (ViewHolder) view.getTag();
            }

            mNetworkImageView = (NetworkImageView) gridViewImageHolder.imageView;
            mNetworkImageView.setDefaultImageResId(R.drawable.ic_launcher);
            mNetworkImageView.setErrorImageResId(android.R.drawable.ic_dialog_alert);
            mNetworkImageView.setAdjustViewBounds(true);
            mNetworkImageView.setImageUrl(imageItems.get(position).get_thumb_path(), imageLoader);

            return view;
        }
    }

Имиджлодер:

imageLoader = MyApplication.getInstance().getImageLoader();
        imageLoader.get(galleryItem.get_imgPath(), imageLoader.getImageListener(img_thumb,
                R.drawable.ic_launcher,
                android.R.drawable.ic_dialog_alert));
        img_thumb.setImageUrl(galleryItem.get_imgPath(), imageLoader);

LruBitmapCache:

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

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

public class LruBitmapCache extends LruCache<String, Bitmap> implements
        ImageCache {
    public static int getDefaultLruCacheSize() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;

        return cacheSize;
    }

    public LruBitmapCache() {
        this(getDefaultLruCacheSize());
    }

    public LruBitmapCache(int sizeInKiloBytes) {
        super(sizeInKiloBytes);
    }

    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
}

что не так с моим кодом. Я устал бороться.


person MSepehr    schedule 11.04.2016    source источник
comment
Используйте Пикассо, чтобы избавиться от борьбы   -  person Zahidul Islam    schedule 11.04.2016
comment
@ZahidulIslam Я должен использовать залп, что не так с залпом?   -  person MSepehr    schedule 11.04.2016


Ответы (2)


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

Например:

mImageLoader = new ImageLoader(this.mRequestQueue,
                new LruBitmapCache()) {
@Override
    protected Request<Bitmap> makeImageRequest(String requestUrl, int maxWidth, int maxHeight,
                ScaleType scaleType, final String cacheKey) {
            return new ImageRequest(requestUrl, new Listener<Bitmap>() {
                @Override
                public void onResponse(Bitmap response) {
                    onGetImageSuccess(cacheKey, response);
                }
            }, maxWidth, maxHeight, scaleType, Config.RGB_565, new ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    onGetImageError(cacheKey, error);
                }
            }){
      @Override
                public Response<Bitmap> parseNetworkResponse(NetworkResponse response) {
                    Response<Bitmap> resp = super.parseNetworkResponse(response);
                    if(!resp.isSuccess()) {
                        return resp;
                    }
                    long now = System.currentTimeMillis();
                    Cache.Entry entry = resp.cacheEntry;
    if(entry == null) {

        entry = new Cache.Entry();
        entry.data = response.data;
        entry.softTtl = now + 1 * 60 * 60 * 1000; // keeps valid(no refresh) for 1hr
        entry.responseHeaders = response.headers;
    }
    entry.ttl = now + 30l * 24 * 60 * 60 * 1000;  //keeps cache for 30 days
                    return Response.success(resp.result, entry);
                }

    };
        }
};

Таким образом, ваши изображения будут кэшироваться на диске в течение 30 дней, а также обновляться при необходимости.

аналогичная проблема здесь

person kalin    schedule 11.04.2016
comment
tnx, проверьте мой следующий ответ. - person MSepehr; 11.04.2016
comment
Могу ли я интегрировать ваш код с моим классом LruBitmapCache? - person MSepehr; 11.04.2016
comment
это не имеет ничего общего с кешем lru в памяти. это обрабатывается дисковым кешем и полностью совместимо с вашим кешем lru. - person kalin; 11.04.2016
comment
обратите внимание, что вам просто нужно создать ImageLoader так, как я вставил - person kalin; 11.04.2016
comment
когда я использую ваш код, он дает мне эту ошибку: java.lang.NullPointerException в этой строке entry.ttl = now + 30l * 24 * 60 * 60 * 1000. log cat доступен в следующем ответе - person MSepehr; 11.04.2016
comment
когда я отлаживаю, показываю, что записи нет! в чем проблема? - person MSepehr; 11.04.2016
comment
Я меняю эту строку: Cache.Entry entry = resp.cacheEntry; to if (entry == null) { entry = new Cache.Entry(); } но это не сработало - person MSepehr; 11.04.2016

Вот как выглядит ответ djodjo в Котлине.

val imageLoader: ImageLoader
    get() {
        requestQueue
        if (mImageLoader == null) {
            mImageLoader = object : ImageLoader(
                this.mRequestQueue,
                LruBitmapCache()
            ) {
                override fun makeImageRequest(
                    requestUrl: String?, maxWidth: Int,
                    maxHeight: Int, scaleType: ImageView.ScaleType?, cacheKey: String?
                ): Request<Bitmap> {
                    return object : ImageRequest(requestUrl,
                        Response.Listener<Bitmap>
                        { response -> onGetImageSuccess(cacheKey, response) },
                        maxWidth,
                        maxHeight,
                        scaleType,
                        Bitmap.Config.RGB_565,
                        Response.ErrorListener {
                            onGetImageError(cacheKey, it)
                        }
                    ) {
                        override fun parseNetworkResponse(response: NetworkResponse?): Response<Bitmap> {
                            val resp = super.parseNetworkResponse(response)
                            if (!resp.isSuccess()) {
                                return resp;
                            }
                            val now = System.currentTimeMillis();
                            var entry = resp.cacheEntry;
                            if (entry == null) {

                                entry = Cache.Entry();
                                entry.data = response?.data;
                                entry.softTtl =
                                    now + 1 * 60 * 60 * 1000; // keeps valid(no refresh) for 1hr
                                entry.responseHeaders = response?.headers;
                            }
                            entry.ttl =
                                now + 30L * 24 * 60 * 60 * 1000;  //keeps cache for 30 days
                            return Response.success(resp.result, entry);
                        }
                    }


                }
            }
        }
        return this.mImageLoader!!
    }

Вот класс LruBitmapCache в Котлине

import android.graphics.Bitmap
import android.util.LruCache
import com.android.volley.toolbox.ImageLoader
class LruBitmapCache @JvmOverloads constructor(sizeInKiloBytes: Int 
defaultLruCacheSize):LruCache<String?, Bitmap>(sizeInKiloBytes),
ImageLoader.ImageCache {
override fun sizeOf(key: String?, value: Bitmap): Int {
    return value.rowBytes * value.height / 1024
}

override fun getBitmap(url: String): Bitmap {
    return get(url)
}

override fun putBitmap(url: String, bitmap: Bitmap) {
    put(url, bitmap)
}

companion object {
    val defaultLruCacheSize: Int
        get() {
            val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
            return maxMemory / 8
        }
}
}

Надеюсь, это может помочь кому-то

person MRamzan    schedule 11.12.2019