volley json cache image doesn't work offline

2020-03-31 08:39发布

问题:

Hello i'm beginner in anroid. I created navigation drawer and fragments. I can getting data from json with url. It's working while online. But phone when offline i'm getting "unable to resolve host" error. I want to get data from url with json while offline. It's not caching enter image description here

fragment

private static final String jsonUrl = "http://sunumsitesi.com/json.php";
private ProgressDialog pDialog;
private List<Urun> urunList = new ArrayList<Urun>();
private ListView listView;
private CustomListAdapter adapter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View root = inflater.inflate(R.layout.fragment_yemek, container, false);
    return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    View v = getView();
    if(v!=null)
    {
        listView = (ListView) v.findViewById(R.id.yemekList);
        adapter = new CustomListAdapter(getActivity(), urunList);
        listView.setAdapter(adapter);

        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Loading...");
        pDialog.show();
        JsonArrayRequest urunReq = new JsonArrayRequest(jsonUrl, new Response.Listener<JSONArray>()
        {
            @Override
            public void onResponse(JSONArray response)
            {
                hidePDialog();
                for (int i = 0; i < response.length(); i++)
                {
                    try
                    {

                        JSONObject obj = response.getJSONObject(i);
                        Urun urun = new Urun();
                        urun.setUrun_adi(obj.getString("urun_adi"));
                        urun.setUrl("http://www.iremdeveci.com/ornekler/resimler/resim.png");//example
                        urunList.add(urun);
                    } catch (JSONException ex)
                    {
                        ex.printStackTrace();
                    }
                }
                adapter.notifyDataSetChanged();
            }
        }, new Response.ErrorListener()
        {
            @Override
            public void onErrorResponse(VolleyError volleyError)
            {
                Toast.makeText(getActivity(), volleyError.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
        AppController.getmInstance().addToRequestQueue(urunReq);
    }
}

@Override
public void onDestroy()
{
    super.onDestroy();
    hidePDialog();
}
private void hidePDialog()
{
    if(pDialog!=null)
    {
        pDialog.dismiss();
        pDialog=null;
    }
}

and CustomListAdapter(extend BaseAdapter)

private Activity activity;
private LayoutInflater inflater;
private List<Urun> urunItems;
ImageLoader imageLoader = AppController.getmInstance().getmImageLoader();
public CustomListAdapter(Activity activity,List<Urun> urunItems)
{
    this.activity=activity;
    this.urunItems=urunItems;
}

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

@Override
public Object getItem(int location)
{
    return urunItems.get(location);
}

@Override
public long getItemId(int position)
{
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    if (inflater==null)
    {
        inflater=(LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    if (convertView==null)
    {
        convertView=inflater.inflate(R.layout.list_row,null);
    }
    if (imageLoader==null)
    {
        imageLoader=AppController.getmInstance().getmImageLoader();
    }
    NetworkImageView urunResim=(NetworkImageView)convertView.findViewById(R.id.urunResim);
    TextView urun_adi= (TextView)convertView.findViewById(R.id.urun_adi);
    Urun u = urunItems.get(position);

    urunResim.setImageUrl(u.getUrl(),imageLoader);
    urun_adi.setText(u.getUrun_adi());
    return convertView;
}

LruBitmapCache.java

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

回答1:

your pictures(http://www.iremdeveci.com/ornekler/resimler/resim.png) seems to be cached correctly as the have etag and cache headers.

However the very first request you make (http://sunumsitesi.com/json.php) doesn't seems to return neither cache headers nor etag. Thus you have the error you dont even reach the picture part.

You can either fix that from the server or make Volley cache it all, for which you need to create custom request and override

protected Response<String> parseNetworkResponse(NetworkResponse response)

You can check my answer here.

In your code this would be smth like

        JsonArrayRequest urunReq = new JsonArrayRequest(jsonUrl, new Response.Listener<JSONArray>()
    {
        @Override
        public void onResponse(JSONArray response)
        {
            String dosyakonum = "http://www.pukkaliving.concept.com/upload/galeri/buyuk/";
            hidePDialog();
            for (int i = 0; i < response.length(); i++)
            {
                try
                {

                    JSONObject obj = response.getJSONObject(i);
                    Urun urun = new Urun();
                    urun.setUrun_adi(obj.getString("urun_adi"));
                    urun.setUrl("http://www.iremdeveci.com/ornekler/resimler/resim.png");//example
                    urunList.add(urun);
                } catch (JSONException ex)
                {
                    ex.printStackTrace();
                }
            }
            adapter.notifyDataSetChanged();
        }
    }, new Response.ErrorListener()
    {
        @Override
        public void onErrorResponse(VolleyError volleyError)
        {
            Toast.makeText(getActivity(), volleyError.getMessage(), Toast.LENGTH_LONG).show();
        }
    }) {
        @Override
        protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
            try {
                String jsonString =
                        new String(response.data, HttpHeaderParser.parseCharset(response.headers));

                long now = System.currentTimeMillis();
                Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
                entry.ttl = now + 30l * 24 * 60 * 60 * 1000;  //keeps cache for 30 days
entry.softTtl = now + 1 * 24 * 60 * 60 * 1000;  //will not try to refresh for 1 day     
                    return Response.success(new JSONArray(jsonString), entry);
                } catch (UnsupportedEncodingException e) {
                    return Response.error(new ParseError(e));
                } catch (JSONException je) {
                    return Response.error(new ParseError(je));
                }
            }
        };
        AppController.getmInstance().addToRequestQueue(urunReq);

however for NetworkImage view you have to customize ImageLoader as this is the one creating the image requests and then the logic is the same. You have to override "makeImageRequest".

ex:

  ...
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;
                        entry.ttl = now + 30l * 24 * 60 * 60 * 1000;  //keeps cache for 30 days
                        return Response.success(resp.result, entry);
                    }

        };
            }
};
    ...