Android的缓存机制返回多结果 [英] Android cache mechanism return multi result
问题描述
在我的缓存机制的请求后添加到请求队列,并尝试从服务器获取数据,我缓存的方法从服务器返回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;
私人列表< DrawerItem> drawer_items =新的ArrayList< DrawerItem>();
私人列表< VideoItems>项目=新的ArrayList<>();
私人DrawerAdatper drawer_adatper = NULL;
私人布尔mDrawerState = 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.016 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屋!