Android缓存机制返回多结果

Android缓存机制返回多结果,android,caching,android-volley,Android,Caching,Android Volley,在我的缓存机制中,将请求添加到RequestQueue并尝试从服务器获取数据后,我的缓存方法从服务器返回多个重复的结果返回json字符串 RequestQueue queue = Volley.newRequestQueue(this); String url = Globals.getHostAddress() + "/get_latest_video"; items.clear(); CacheRequest cacheRequest = new CacheRequest(0, url,

在我的缓存机制中,将请求添加到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}
缓存数据和使用它的代码有什么问题

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);
    }
}
服务器响应结果我正在使用浏览器进行测试:

[{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]
不幸的是,此重复结果是随机的(并非每次都重复)

更新3:

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);
    }
}
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.
                            }
                        }
                    });
                }
依我看,可能是
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);

您可以在“Log.e(“allVideos”,jsonString);”中找到重复的输出?请发布您的日志如果您的意思是
项目
列表中有重复的项目,那么我找不到您更新日志的位置list@BNK您好,先生。是的,{code>{id:12,“channel\u id:7”,“category\u id:8},{id:12,“channel\u id:7”,“category\u id:8}是我的日志结果,我的
项目列表非常简单,我将更新帖子以再次查看,先生。我想如果我的手机上同时有internet连接和缓存数据,我的结果是重复的。@BNK我正在尝试使用缓存,而不使用数据库从中检索数据并再次解析,ThanksIt很奇怪,我的项目没有得到重复的输出。你能发布你的完整日志信息吗?如果它是
{“id”:12,“channel_id”:7,“category_id”:8},{“id”:12,“channel_id”:7,“category_id”:‌​8} 
我认为行
JSONArray-JSONArray=newjsonarray(jsonString)抛出异常,因为jsonString不是json数组您尝试过setRetryPolicy了吗?关于我的项目,我现在不能发布,因为我在手机上:)如上所述,建议你从这里获取谷歌的官方截图git clone来查看更多细节。不,先生。我正在更改服务器响应头并将缓存设置为该值。之后我删除了
cacheRequest
,我想问题解决了,我没有重复的结果。当你们有空的时候,我想你们可以用
setRetryPolicy
测试
cacheRequest
,看看它是否可以修复。我还并没有试着检查互联网连接,不过,正如我在上面的问题中所评论的,对于刷新,如果需要从原始数据源进行刷新,我认为您可以在Cache.java
/**中找到True。*/public boolean refreshNeeded(){返回this.softTtl
,您可以更新或使softTtl变小,甚至0。当然,您必须检查internet连接是否可用
                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.
                            }
                        }
                    });
                }
cacheRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 2, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
// Add the request to the RequestQueue.
queue.add(cacheRequest);