Android缓存机制返回多个结果



在我的缓存机制中将请求添加到RequestQueue并尝试从服务器获取数据后,我的缓存方法从服务器返回多个重复结果返回json字符串

RequestQueue queue = Volley.newRequestQueue(this);
String url = Globals.getHostAddress() + "/get_latest_video";
items.clear();
CacheRequest cacheRequest = new CacheRequest(0, url, new Response.Listener<NetworkResponse>() {
    @Override
    public void onResponse(NetworkResponse response) {
        try {
            final String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            Log.e("allVideos", jsonString);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } 
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
    }
});
// Add the request to the RequestQueue.
queue.add(cacheRequest);

服务器返回此结果:

{"id":12,"channel_id":7,"category_id":8}

缓存机制返回:

{"id":12,"channel_id":7,"category_id":8},{"id":12,"channel_id":7,"category_id":8}

缓存数据和使用数据的代码问题是什么?

CacheRequest类内容:

public class CacheRequest extends Request<NetworkResponse> {
    private final Response.Listener<NetworkResponse> mListener;
    private final Response.ErrorListener mErrorListener;
    public CacheRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mListener = listener;
        this.mErrorListener = errorListener;
    }

    @Override
    protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
        Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
        if (cacheEntry == null) {
            cacheEntry = new Cache.Entry();
        }
        final long cacheHitButRefreshed = 3 * 60 * 1000; // in 3 minutes cache will be hit, but also refreshed on background
        final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
        long now = System.currentTimeMillis();
        final long softExpire = now + cacheHitButRefreshed;
        final long ttl = now + cacheExpired;
        cacheEntry.data = response.data;
        cacheEntry.softTtl = softExpire;
        cacheEntry.ttl = ttl;
        String headerValue;
        headerValue = response.headers.get("Date");
        if (headerValue != null) {
            cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
        }
        headerValue = response.headers.get("Last-Modified");
        if (headerValue != null) {
            cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
        }
        cacheEntry.responseHeaders = response.headers;
        return Response.success(response, cacheEntry);
    }
    @Override
    protected void deliverResponse(NetworkResponse response) {
        mListener.onResponse(response);
    }
    @Override
    protected VolleyError parseNetworkError(VolleyError volleyError) {
        return super.parseNetworkError(volleyError);
    }
    @Override
    public void deliverError(VolleyError error) {
        mErrorListener.onErrorResponse(error);
    }
}

更新的帖子:

public class ActivityBootstrap extends Activity implements AdapterView.OnItemClickListener {
    @InjectView(R.id.drawer_list)
    ListView drawer_list;
    @InjectView(R.id.drawer_layout)
    DrawerLayout drawer_layout;
    @InjectView(R.id.listView)
    AsymmetricGridView listView;
    private List<DrawerItem> drawer_items = new ArrayList<DrawerItem>();
    private List<VideoItems> items = new ArrayList<>();
    private DrawerAdatper drawer_adatper = null;
    private boolean mDrawerState = false;
    private VideoAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        RequestQueue queue = Volley.newRequestQueue(this);
        String url = Globals.getHostAddress() + "/get_latest_video";
        items.clear();
        CacheRequest cacheRequest = new CacheRequest(0, url, new Response.Listener<NetworkResponse>() {
            @Override
            public void onResponse(NetworkResponse response) {
                try {
                    final String jsonString = new String(response.data,
                            HttpHeaderParser.parseCharset(response.headers));
                    Log.e("allVideos", jsonString);
                    JSONArray jsonArray = new JSONArray(jsonString);
                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject video_single_item = jsonArray.getJSONObject(i);
                        int video_id = video_single_item.getInt("id");
                        String video_thumbnail = video_single_item.getString("thumbnail");
                        int colSpan = Math.random() < 0.2f ? 2 : 1;
                        int rowSpan = colSpan;
                        VideoItems item = new VideoItems(colSpan, rowSpan, video_thumbnail,video_id);
                        items.add(item);
                    }
                    setUpListView(items);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
            }
        });
        // Add the request to the RequestQueue.
        queue.add(cacheRequest);
    }
    private void setUpListView(List video_array_items) {
        final List<AsymmetricItem> items = new ArrayList<>();
        adapter = new VideoListAdapter(this, video_array_items);
        AsymmetricGridViewAdapter asymmetricAdapter =
                new AsymmetricGridViewAdapter<>(this, listView, adapter);
        listView.setAdapter(asymmetricAdapter);
        listView.setRequestedColumnCount(3);
        listView.setAdapter(getNewAdapter());
        listView.setOnItemClickListener(this);
        listView.setAllowReordering(true);
        listView.isAllowReordering();
    }
    private AsymmetricGridViewAdapter<?> getNewAdapter() {
        return new AsymmetricGridViewAdapter<>(this, listView, adapter);
    }
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        int video_position = items.get(position).getVideo_id();
        Intent intent = new Intent(ActivityBootstrap.this, ActivitySHowVideoDetaile.class);
        intent.putExtra("video_id", video_position);
        startActivity(intent);
    }
}

更新后的帖子2)

Log.e("allVideos", jsonString);的结果是:

10-28 09:51:46.016 17872-17872/pishguy.ir.asrebidree E/allVideos: [{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]
10-28 09:51:47.249 17872-17872/pishguy.ir.asrebidree E/allVideos: [{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]

服务器响应的结果我用浏览器测试它:

[{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]

不幸的是,此重复结果是随机的(并非每次都重复)

更新3:

10-28 13:14:52.322 16129-16129/pishguy.ir.asrebidree E/Test: onCreate called
10-28 13:14:52.513 16129-16129/pishguy.ir.asrebidree E/allVideos: [{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]
10-28 13:14:53.206 16129-16129/pishguy.ir.asrebidree E/allVideos: [{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]

因为我评论了太多行,我无法将"重复行为"作为您当前的问题重新生成,所以我在这里发布了我的答案,希望这能有所帮助!

CacheDispatcher类中,您会发现以下内容:

                if (!entry.refreshNeeded()) {
                    // Completely unexpired cache hit. Just deliver the response.
                    mDelivery.postResponse(request, response);
                } else {
                    // Soft-expired cache hit. We can deliver the cached response,
                    // but we need to also send the request to the network for
                    // refreshing.
                    request.addMarker("cache-hit-refresh-needed");
                    request.setCacheEntry(entry);
                    // Mark the response as intermediate.
                    response.intermediate = true;
                    // Post the intermediate response back to the user and have
                    // the delivery then forward the request along to the network.
                    mDelivery.postResponse(request, response, new Runnable() {
                        @Override
                        public void run() {
                            try {
                                mNetworkQueue.put(request);
                            } catch (InterruptedException e) {
                                // Not much we can do about this.
                            }
                        }
                    });
                }

IMO,可能是softTtl导致了这种复制行为。

我建议您使用以下行为您的请求设置RetryPolicy:

cacheRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 2, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
// Add the request to the RequestQueue.
queue.add(cacheRequest);

最新更新