Volley L2 캐시 읽기 문제

6479 단어

묻다


네트워크가 없는 경우 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의 원본 코드는 정말 반복해서 볼 만하고, 궁리하고, 모방할 만하다.
스스로 원본을 보고, 아래에서 원본을 분석하고, 아래의 문제를 검사하다
  • Volley가 L2 캐시를 구현하는지 확인합니다.
  • L2 캐시는 언제 저장됩니까?
  • L2 저장 성공 후 사용 여부
  • 문제 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) 라고 짐작할 수 있다.쐐기------------------이 문제를 우리 팀은 대략 일주일을 써서 해결했다. 진도가 늦어졌지만 수확이 꽤 많았던 기간에도 다른 그림으로 프레임워크를 캐시하자고 했는데, 이런 독주로 갈증을 해소하는 방식이 어떻게

    좋은 웹페이지 즐겨찾기