Volley L2 캐시 읽기 문제
묻다
네트워크가 없는 경우 Volley의 L2(HDD) 캐시가 작동하지 않음
답안
*** 서버의 Response 헤더에'cache-control:public, max-age=43200'(예시)***
원리
간단하게 말하자면 Volley 프레임워크가 고려하는 것은 비교적 전면적이다. 단말기(핸드폰이나 브라우저)의 캐시 정책은 서버에서 제정한 것이고, Volley는 캐시를 하기 전에 서버가 스스로 이 캐시를 할 수 있는지 판단한다.서버 캐시가 부족한 상황에서 터미널을 캐시하지 못하게 합니다
캐시에 대한 자세한 내용은 HTTP 캐시 이동 - Web Fundamentals
구해 과정
이 문제는 우리 팀에서도 전에 Google이 얻은 정보는 Volley가 L2 캐시(하드 디스크 기반)를 실현했기 때문에 자체적으로 L1 캐시(메모리 기반)를 실현해야 한다는 것이다.L2 캐시가 이미 실현되었으니 네트워크가 없는 상황에서 그림을 불러올 수 있습니다.한 파트너는 서로 다른 URL을 사용하면 L2 캐시의 실현에 영향을 줄 수 있다는 것을 발견했다.
원본 보기, 다른 사람이 쓴 원본 해석 먼저 보기 Volley 원본 해석 Android 네트워크 통신 프레임워크 Volley 프로필(Google IO 2013) Android Volley 완전 해석(一), Volley의 기본 사용법 초식https://developer.android.com/training/volley/index.html ..... 지난 2, 3일 동안 한 번씩 훑어보았는데 Volley가 여유롭게 쓴 것 외에는 큰 도움이 되지 않았다.Volley의 원본 코드는 정말 반복해서 볼 만하고, 궁리하고, 모방할 만하다.
스스로 원본을 보고, 아래에서 원본을 분석하고, 아래의 문제를 검사하다
문제 1
public staticRequestQueue newRequestQueue(Context context,HttpStack stack) {
File cacheDir =newFile(context.getCacheDir(),"volley");
String userAgent ="volley/0";
try{
String network = context.getPackageName();
PackageInfo queue = context.getPackageManager().getPackageInfo(network,0);
userAgent = network +"/"+ queue.versionCode;
}catch(NameNotFoundException var6) {
}
if(stack ==null) {
if(VERSION.SDK_INT >=9) {
stack =newHurlStack();
}else{
stack =newHttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
BasicNetwork network1 =newBasicNetwork((HttpStack)stack);
RequestQueue queue1 =newRequestQueue(newDiskBasedCache(cacheDir),network1);
queue1.start();
returnqueue1;
}
호출
Volley.newRequestQueue(Context)
요청 대기열을 만들 때 L2 캐시가 생성됨문제 2
public void start() {
this.stop();
this.mCacheDispatcher = newCacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
this.mCacheDispatcher.start();
}
대기열을 시작하고 CacheDispatcher와 NetworkDispatcher에 대해 생각합니다. 처음에는 캐시 상태가 없으므로 NetworkDispatcher만 사용해야 합니다. 따라서 NetworkDispatcher만 주목해야 합니다.
public void run() {
Process.setThreadPriority(10);
// ,
while (true) {
Requestrequest;
while (true) {
try {
request = (Request) this.mQueue.take();
break;
} catch (InterruptedExceptionvar4) {
if (this.mQuit) {
return;
}
}
}
// ,
try {
request.addMarker("network-queue-take");
if (request.isCanceled()) {
request.finish("network-discard-cancelled");
} else {
if (VERSION.SDK_INT >= 14) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
// Response , NetworkResponsee=this.mNetwork.performRequest(request);request.addMarker("network-http-complete");if(e.notModified&&request.hasHadResponseDelivered()){request.finish("not-modified");}else{
// Volley Response , Responseresponse=request.parseNetworkResponse(e);request.addMarker("network-parse-complete");
if (request.shouldCache() && response.cacheEntry != null) {
this.mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
request.markDelivered();
this.mDelivery.postResponse(request, response);
}
}
}catch(VolleyErrorvar5) {this.parseAndDeliverNetworkError(request, var5);
}catch(Exceptionvar6) {VolleyLog.e(var6, "Unhandled exception %s", newObject[]{
var6.toString()
});
this.mDelivery.postError(request, newVolleyError(var6));}}
원래는 요청에 중점을 두었다.shouldCache()l&&response.cacheEntry != nul 캐시 여부 판단!계속 누르세요.
public final boolean shouldCache() {
return this.mShouldCache;
}
구조 방법에서 볼 수 있다
public Request(int method, String url, ErrorListener listener) {
this.mEventLog = MarkerLog.ENABLED?new MarkerLog():null;
this.mShouldCache = true;
//
this.mCanceled = false;
this.mResponseDelivered = false;
this.mRequestBirthTime = 0L;
this.mCacheEntry = null;
this.mMethod = method;
this.mUrl = url;
this.mErrorListener = listener;
this.setRetryPolicy(new DefaultRetryPolicy());
this.mDefaultTrafficStatsTag = TextUtils.isEmpty(url)?0:Uri.parse(url).getHost().hashCode();
}
cacheEntry
는 Request를 상속할 때 다시 작성해야 합니다. 예를 들어 StringRequest
parsed = new String(response.data,HttpHeaderParser.parseCharset(response.headers));
좋아요.이 결과도 예상됐다.
안드로이드 시뮬레이터를 사용할 때도/데이터/데이터/패키지 이름/volley/...디렉터리에 그림 파일 생성
캐시를 호출할 때 무슨 일이 일어났는지 계속 보세요.
질문
코드가 좀 많아요. 바로 붙이는 게 제일 중요해요.
final Request e = (Request)this.mCacheQueue.take();
e.addMarker("cache-queue-take");
if(e.isCanceled()) {
e.finish("cache-discard-canceled");
} else {
Entry entry = this.mCache.get(e.getCacheKey());
if(entry == null) {
e.addMarker("cache-miss");
this.mNetworkQueue.put(e);
// !
} else if(entry.isExpired()) {
e.addMarker("cache-hit-expired");
e.setCacheEntry(entry);
this.mNetworkQueue.put(e);
}
// ....
L2 캐시는 요청 URL을 통해cache-key로 저장됩니다.그래서 entry.isExpired()가 포인트!
하면, 만약, 만약...isExpired()는true로 캐시를 반환하고false는 네트워크 요청 대기열에 들어가 네트워크 요청을 계속합니다
public boolean isExpired() {
return this.ttl < System.currentTimeMillis();
}
ttl!ttl!ttl!
위의 그 사이트 주소와 결합하여ttl!컴퓨터를 그렇게 오래 배우면 캐시의 생명주기 (time to live) 라고 짐작할 수 있다.쐐기------------------이 문제를 우리 팀은 대략 일주일을 써서 해결했다. 진도가 늦어졌지만 수확이 꽤 많았던 기간에도 다른 그림으로 프레임워크를 캐시하자고 했는데, 이런 독주로 갈증을 해소하는 방식이 어떻게
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.