Android Volley tidak menyimpan gambar dalam cache

Saya menggunakan ini tutorial untuk menampilkan dan menyimpan gambar dalam grid menggunakan Volley. ketika internet terhubung, itu berfungsi dengan baik. tetapi setelah terputus, gambar tidak muncul. sepertinya Volley tidak menyimpan gambar apa pun dalam cache. Masalahnya, belum ada dokumentasi lengkap tentang caching image menggunakan Volley. Ini kode saya:

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

adaptor:

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

Pembuat gambar:

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

apa yang salah dengan kode saya. Saya lelah berjuang.


person MSepehr    schedule 11.04.2016    source sumber
comment
Gunakan Picasso untuk menghilangkan kesulitan   -  person Zahidul Islam    schedule 11.04.2016
comment
@ZahidulIslam saya harus pakai volley, apa salahnya volley?   -  person MSepehr    schedule 11.04.2016


Jawaban (2)


tampaknya masalahnya adalah gambar Anda tidak memiliki header cache yang memberitahu Volley untuk menyimpannya dalam cache. Anda dapat secara eksplisit memaksa cache dengan memperluas ImageLoader yang Anda inisialisasi di MyApplication.

Misalnya:

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

    };
        }
};

Dengan cara ini gambar Anda akan disimpan dalam cache di disk selama 30 hari tetapi juga disegarkan bila diperlukan.

masalah serupa di sini

person kalin    schedule 11.04.2016
comment
terima kasih, periksa jawaban saya selanjutnya. - person MSepehr; 11.04.2016
comment
bisakah saya mengintegrasikan kode Anda dengan kelas LruBitmapCache saya? - person MSepehr; 11.04.2016
comment
ini tidak ada hubungannya dengan cache di memori lru. ini ditangani oleh diskbasedcache dan sangat kompatibel dengan cache lru Anda - person kalin; 11.04.2016
comment
perhatikan bahwa Anda hanya perlu membuat ImageLoader seperti yang saya tempel - person kalin; 11.04.2016
comment
ketika saya menggunakan kode Anda, saya mendapat kesalahan ini: java.lang.NullPointerException di baris ini entry.ttl = sekarang + 30l * 24 * 60 * 60 * 1000. log cat tersedia di jawaban berikutnya - person MSepehr; 11.04.2016
comment
ketika saya men-debug, tunjukkan bahwa entri itu tidak! Apa masalahnya? - person MSepehr; 11.04.2016
comment
Saya mengubah baris ini: Cache.Entry entry = resp.cacheEntry; ke if (entri == null) { entri = new Cache.Entry(); } tetapi tidak berhasil - person MSepehr; 11.04.2016

Inilah jawaban Djodjo di Kotlin.

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

Berikut adalah kelas LruBitmapCache di Kotlin

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

Semoga ini bisa membantu seseorang

person MRamzan    schedule 11.12.2019