Android的缓存机制返回多结果 [英] Android cache mechanism return multi result

查看:111
本文介绍了Android的缓存机制返回多结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 请求队列排队= Volley.newRequestQueue(本);
字符串URL = Globals.getHostAddress()+/ get_latest_video;

items.clear();
CacheRequest cacheRequest =新CacheRequest(0,网址,新Response.Listener< NetworkResponse>(){
    @覆盖
    公共无效onResponse(NetworkResponse响应){
        尝试 {
            最后弦乐jsonString =新的String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            Log.e(allVideos,jsonString);
        }赶上(UnsupportedEncodingException E){
            e.printStackTrace();
        }
    }
},新Response.ErrorListener(){
    @覆盖
    公共无效onErrorResponse(VolleyError错误){
    }
});
//增加请求到请求队列。
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 }
 

什么我的code问题来缓存数据和使用?

CacheRequest 类的内容:

 公共类CacheRequest扩展请求< NetworkResponse> {
    私人最终Response.Listener< NetworkResponse> mListener;
    私人最终Response.ErrorListener mErrorListener;

    公共CacheRequest(INT方法,字符串URL,Response.Listener< NetworkResponse>听者,Response.ErrorListener errorListener){
        超(方法,URL,errorListener);
        this.mListener =侦听器;
        this.mErrorListener = errorListener;
    }


    @覆盖
    受保护的响应和LT; NetworkResponse> parseNetworkResponse(NetworkResponse响应){
        Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(响应);
        如果(cacheEntry == NULL){
            cacheEntry =新Cache.Entry();
        }
        最终长cacheHitButRefreshed = 3 * 60 * 1000; //在3分钟内缓存将受到较大冲击,同时也刷新的背景
        最终长cacheExpired = 24 * 60 * 60 * 1000; //在24小时内这个缓存条目完全失效
        长今= System.currentTimeMillis的();
        最终长softExpire =现在+ cacheHitButRefreshed;
        最终长TTL =现在+ cacheExpired;
        cacheEntry.data = response.data;
        cacheEntry.softTtl = softExpire;
        cacheEntry.ttl = TTL;
        字符串headerValue;
        headerValue = response.headers.get(日期);
        如果(headerValue!= NULL){
            cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
        }
        headerValue = response.headers.get(上次修改);
        如果(headerValue!= NULL){
            cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
        }
        cacheEntry.responseHeaders = response.headers;
        返回Response.success(响应,cacheEntry);
    }

    @覆盖
    保护无效deliverResponse(NetworkResponse响应){
        mListener.onResponse(响应);
    }

    @覆盖
    保护VolleyError parseNetworkError(VolleyError volleyError){
        返回super.parseNetworkError(volleyError);
    }

    @覆盖
    公共无效deliverError(VolleyError错误){
        mErrorListener.onErrorResponse(错误);
    }
}
 

修订POST:

 公共类ActivityBootstrap扩展活动实现AdapterView.OnItemClickListener {

    @InjectView(R.id.drawer_list)
    ListView控件drawer_list;

    @InjectView(R.id.drawer_layout)
    DrawerLayout drawer_layout;

    @InjectView(R.id.listView)
    AsymmetricGridView的ListView;

    私人列表< D​​rawerItem> drawer_items =新的ArrayList< D​​rawerItem>();
    私人列表< VideoItems>项目=新的ArrayList<>();
    私人DrawerAdatper drawer_adatper = NULL;
    私人布尔mD​​rawerState = FALSE;
    私人VideoAdapter适配器;
    @覆盖
    保护无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
        ButterKnife.inject(本);

        请求队列排队= Volley.newRequestQueue(本);
        字符串URL = Globals.getHostAddress()+/ get_latest_video;

        items.clear();
        CacheRequest cacheRequest =新CacheRequest(0,网址,新Response.Listener< NetworkResponse>(){
            @覆盖
            公共无效onResponse(NetworkResponse响应){
                尝试 {
                    最后弦乐jsonString =新的String(response.data,
                            HttpHeaderParser.parseCharset(response.headers));
                    Log.e(allVideos,jsonString);
                    JSONArray jsonArray =新JSONArray(jsonString);
                    的for(int i = 0; I< jsonArray.length();我++){
                        的JSONObject video_single_item = jsonArray.getJSONObject(ⅰ);
                        INT VIDEO_ID = video_single_item.getInt(ID);
                        字符串video_thumbnail = video_single_item.getString(缩略图);
                        INT COLSPAN =的Math.random()< 0.2F? 2:1;
                        INT ROWSPAN = COLSPAN;
                        VideoItems项目=新VideoItems(合并单元格,行跨度,video_thumbnail,VIDEO_ID);
                        items.add(项目);
                    }
                    setUpListView(项目);
                }赶上(UnsupportedEncodingException E){
                    e.printStackTrace();
                }赶上(JSONException E){
                    e.printStackTrace();
                }
            }
        },新Response.ErrorListener(){
            @覆盖
            公共无效onErrorResponse(VolleyError错误){
            }
        });
        //增加请求到请求队列。
        queue.add(cacheRequest);

    }

    私人无效setUpListView(名单video_array_items){
        最后的名单,其中,AsymmetricItem>项目=新的ArrayList<>();

        适配器=新VideoListAdapter(这一点,video_array_items);
        AsymmetricGridViewAdapter asymmetricAdapter =
                新AsymmetricGridViewAdapter<>(这一点,ListView中,适配器);
        listView.setAdapter(asymmetricAdapter);
        listView.setRequestedColumnCount(3);
        listView.setAdapter(getNewAdapter());
        listView.setOnItemClickListener(本);
        listView.setAllowReordering(真正的);
        listView.isAllowReordering();
    }

    私人AsymmetricGridViewAdapter<> getNewAdapter(){
        返回新AsymmetricGridViewAdapter<>(这一点,ListView中,适配器);
    }

    @覆盖
    公共无效onItemClick(适配器视图<>适配器视图,视图中查看,INT位置,长的id){
        INT video_position = items.get(位置).getVideo_id();

        意向意图=新的意图(ActivityBootstrap.this,ActivitySHowVideoDetaile.class);
        intent.putExtra(VIDEO_ID,video_position);
        startActivity(意向);
    }
}
 

修订POST 2)

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

 九月10号至28日:51:46.0​​16 17872-17872 / pishguy.ir.asrebidree E / allVideos: [{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]
9月一十日日至28日:51:47.249 17872-17872 / pishguy.ir.asrebidree E / allVideos: [{"id":12,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"},{"id":10,"thumbnail":"1445615983c92d10f1f3ee907150be1fdb8184ca893178682-360p__19106.png"}]
 

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

<$p$p><$c$c>[{"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 /测试:所谓的onCreate
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 类,你会发现以下内容:

 如果(!entry.refreshNeeded()){
                    //完全过期的缓存命中。刚刚传送的响应。
                    mDelivery.postResponse(请求,响应);
                } 其他 {
                    //软过期的缓存命中。我们可以提供缓存的响应,
                    //但是我们还需要将请求发送到网络
                    //耳目一新。
                    request.addMarker(缓存命中刷新需要的);
                    request.setCacheEntry(入口);

                    //标记的响应作为中间。
                    response.intermediate = TRUE;

                    //邮政中间响应返回给用户,并有
                    //交付则请求跟着网络转发。
                    mDelivery.postResponse(请求,响应,新的可运行(){
                        @覆盖
                        公共无效的run(){
                            尝试 {
                                mNetworkQueue.put(要求);
                            }赶上(InterruptedException异常E){
                                //不多,我们可以做到这一点。
                            }
                        }
                    });
                }
 

国际海事组织,则可能是 softTtl 是导致这种重复的行为。

我建议您使用以下行setRetryPolicy为您的要求:

  cacheRequest.setRetryPolicy(新DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 2,0,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
//增加请求到请求队列。
queue.add(cacheRequest);
 

in my cache mechanism after add the request to the RequestQueue and try to fetch data from server, my cache method return multi duplicate result from server return json string

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

server return this result:

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

Cache mechanism return :

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

whats my code problem to cache data and using that?

CacheRequest class content:

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

UPDATED POST:

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

UPDATED POST 2)

Result of Log.e("allVideos", jsonString); is :

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

Result of server response i'm test it with browser:

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

UNFORTUNATELY this duplicate result is random(NOT duplicate every time)

UPDATE 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"}]

解决方案

Because I have commented too many lines and I cannot re-produce "duplication behavior" as your current issue, so I post my answer here, hope this helps!

Inside CacheDispatcher class, you will find the following:

                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, it is possible the softTtl that is causing this duplication behavior.

I suggest that you use the following line to setRetryPolicy for your request:

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

这篇关于Android的缓存机制返回多结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆