Volley 소스 분석 (1) RequestQueue 분석
Volley 소스 분석
2017년에volley는 점차적으로 도태되는 틀이지만 코드가 짧고 정교하며 네트워크 구조 설계가 교묘하여 배울 점이 많다.첫 번째 글은 요청 대기열의 코드를 분석했는데 요청 대기열도 우리가 Volley를 사용하는 관건적인 단계이다.두 번째 글은 디스패치를 분석할 거예요.
RequestQueue
RequestQueue 객체를 만드는 방법은 다음과 같습니다.
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
대기열은 Http 요청을 시작하는 데 사용됩니다.주로 newRequestQueue 방법을 보는데 이 방법의 핵심 실현은 2개의 매개 변수의 방법이다
newRequestQueue(Context context, HttpStack stack)
이 방법은 다음과 같습니다.
Network network = new BasicNetwork(stack);
만들어진 CacheDir로 DiskBasedCache 대상을 초기화하여 RequestQueue 대상의 초기화를 완성한다RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
다음은 HttpStack의 역할과DiskBasedCache와 NetWork의 역할, 마지막으로 start 방법이 무엇을 했는지 살펴보겠습니다.
HttpStack은 하나의 인터페이스로 이 인터페이스는 두 개의 실현 클래스만 있는데 하나는 HttpClientStack이고 다른 하나는 HulStack이다.우리는 먼저 구체적인 실현류를 보지 않고 인터페이스 방법의 성명만 본다.
HttpResponse performRequest(Request> request, Map additionalHeaders)
throws IOException, AuthFailureError;
이 방법의 역할은 진정으로 인터넷 요청을 하는 데 쓰인다. 구체적으로 그런 http 실현 클래스로 요청을 하면 HttpClient와 HttpUrl로 나뉜다.
NetWork 인터페이스를 보면 이 인터페이스는 하나의 실현 클래스만 있고 BasicNetWork는 구체적인 실현 클래스를 보지 않고 인터페이스의 방법만 보면 다음과 같다.
NetworkResponse performRequest(Request> request) throws VolleyError;
이 메서드는 지정된 Request를 실행하는 방법에 대해 설명합니다.
마지막으로 DiskBasedCache의 기능을 살펴보겠습니다.이 클래스는 Cache의 구체적인 실현 클래스로 캐시된 파일로 하드디스크에 존재하며 기본 하드디스크 크기는 5M이다.위의 몇 개의 인터페이스 기능은 모두 끝났고, 실제 클래스의 대상을 통해 최종적으로 RequestQueue를 구성했다.다음은 구조기 방법의 집행을 살펴보자.
RequestQueue의 구성원 변수 및 방법
먼저 RequestQueue의 구성원 변수에 대해 살펴보겠습니다.
다음은 구조 방법을 살펴보겠습니다.
public RequestQueue(Cache cache, Network network, int threadPoolSize,
ResponseDelivery delivery) {
mCache = cache;
mNetwork = network;
mDispatchers = new NetworkDispatcher[threadPoolSize];
mDelivery = delivery;
}
몇 개의 매개 변수의 구조 방법을 막론하고 최종적으로 이것을 집행할 것이다.위쪽
new RequestQueue
에서 우리가 전송하는 구조 방법은 Cache와 NetWork 대상밖에 없다. 그러면threadPoolsize는 기본적으로 4이고delivery는new ExecutorDelivery(new Handler(Looper.getMainLooper()))
이ExecutorDelivery에 대해 뒤에서 분석한다.다음은 RequestQueue의 주요 접근 방식을 살펴보겠습니다.
stop 방법
public void stop() {
if (mCacheDispatcher != null) {
mCacheDispatcher.quit();
}
for (final NetworkDispatcher mDispatcher : mDispatchers) {
if (mDispatcher != null) {
mDispatcher.quit();
}
}
}
stop 방법의 모든 코드는 매우 적습니다. 주로 하는 일은 다음과 같습니다.
관건은 퀴즈 방법에 있다.
quit 메서드의 코드는 다음과 같습니다.
public void quit() {
mQuit = true;
interrupt();
}
CacheDispatcher는 상속 및 Thread입니다.quit 방법의 역할은 종료된 로고 위치를 설정하고interrupt 방법을 호출하는 것입니다.run 방법이 실행되는 과정에서 라인이 중단되어catch 문장 블록의 내용을 실행하고 로고 위치를 검사하며 직접return을 실행합니다.
다음은 자신의 기능과 관련된 코드를 제거한 후 남은 부분이다.아주 표준적인 라인 퇴출 기법임을 알 수 있다.
public void run() {
// ,
while (true) {
try {
// ,
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
}
}
}
stop 방법 분석 완료
start 방법
public void start() {
stop(); // Make sure any currently running dispatchers are stopped.
// Create the cache dispatcher and start it.
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
// Create network dispatchers (and corresponding threads) up to the pool size.
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
start 방법이 비교적 간결하기 때문에 나는 여기에 모든 방법의 원본 코드를 내보낸다.start 방법은 주로 다음과 같은 몇 가지를 했다.
stop 방법은 위에서 분석한 바와 같이 더 이상 말하지 않겠습니다. stop을 먼저 호출하는 목적은 이미 시작된 디스패치를 먼저 멈추는 것입니다.
CacheDispather, NetWork Dispatcher를 만듭니다. 그들은 사실 하나의 라인입니다. 그들의 start 방법을 호출합니다.그들의 분석에 관해서는 뒤에 구체적으로 소개한다.
cancel 방법
cancel 방법은 실제로는 cancalAll 방법이지만, 실제로는 최종적으로 cancelAll (RequestFilter Filter) 필터를 호출합니다. 실제로는 취소할 Request를 필터합니다.그리고 Request를 호출합니다.cancel. 리퀘스트 클래스에 대한 분석을 뒤에 두십시오.
finish 방법
void finish(Request request) {
// Remove from the set of requests currently being processed.
synchronized (mCurrentRequests) {
mCurrentRequests.remove(request);
}
synchronized (mFinishedListeners) {
for (RequestFinishedListener listener : mFinishedListeners) {
listener.onRequestFinished(request);
}
}
if (request.shouldCache()) {
synchronized (mWaitingRequests) {
String cacheKey = request.getCacheKey();
Queue> waitingRequests = mWaitingRequests.remove(cacheKey);
if (waitingRequests != null) {
if (VolleyLog.DEBUG) {
VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.",
waitingRequests.size(), cacheKey);
}
// Process all queued up requests. They won't be considered as in flight, but
// that's not a problem as the cache has been primed by 'request'.
mCacheQueue.addAll(waitingRequests);
}
}
}
}
finish 방법은 일반적인 방법으로 이finish 방법은 다음과 같은 몇 가지 일을 집행했다.
위의 구성원 변수 설명에서currentRequst는 실제적으로 파견되거나 실행 중인 Request를 저장하고finish는 당연히 이 대기열에서 제거합니다.
/** Callback interface for completed requests. */
public interface RequestFinishedListener {
/** Called when a request has finished processing. */
void onRequestFinished(Request request);
}
이 인터페이스의 목적은 리퀘스트가 끝난 후에 리셋하는 인터페이스를 제공하는 것이다.
리퀘스트에 캐시가 필요한지 판단하려면 set Should Cache 설정을 통해 mWaiting Reuqests에서 키에 대응하는 대기열을 제거하고cacheQueue에 대기열을 추가할 수 있습니다.즉, waitingQueue에 같은 Request가 존재한다면 모두 제거합니다.
add 방법
add 방법은 리퀘스트를 추가하는 방법입니다. 모든 코드는 다음과 같습니다.
public Request add(Request request) {
// Tag the request as belonging to this queue and add it to the set of current requests.
request.setRequestQueue(this);
synchronized (mCurrentRequests) {
mCurrentRequests.add(request);
}
// Process requests in the order they are added.
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
// If the request is uncacheable, skip the cache queue and go straight to the network.
if (!request.shouldCache()) {
mNetworkQueue.add(request);
return request;
}
// Insert request into stage if there's already a request with the same cache key in flight.
synchronized (mWaitingRequests) {
String cacheKey = request.getCacheKey();
if (mWaitingRequests.containsKey(cacheKey)) {
// There is already a request in flight. Queue up.
Queue> stagedRequests = mWaitingRequests.get(cacheKey);
if (stagedRequests == null) {
stagedRequests = new LinkedList>();
}
stagedRequests.add(request);
mWaitingRequests.put(cacheKey, stagedRequests);
if (VolleyLog.DEBUG) {
VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
}
} else {
// Insert 'null' queue for this cacheKey, indicating there is now a request in
// flight.
mWaitingRequests.put(cacheKey, null);
mCacheQueue.add(request);
}
return request;
}
}
현재 RequestQueue에 Request를 연결하고 mCurrentRequeue에 이 Request를 추가합니다. Request는 대기열에 가입하는 순서를 설정하여 이 Request에 캐시가 필요한지 판단합니다. 캐시가 필요하지 않으면 넷워크Queue에 직접 가입하여 실행되기를 기다립니다.캐시가 필요하면, 이 Waiting Request에 이 Request가 있는지 판단하고, 있으면 이cacheKey에 대응하는 대기열을 얻고, 이 Request를 추가하고, 없으면 Staged Requests를 만들어서 추가합니다.그런 다음 StagedRequests를 WaitingRequest에 넣습니다.cacheKey가 없으면waitingRequest는cacheKey,value는null의 값을 삽입하고,cacheQueue에 Request를 추가합니다.
이로써 RequestQueue 부분은 분석이 끝났습니다. 그 주요 기능은 전송된 Request에 따라 이 Request를 그 Queue에 추가하고 Dispatcher를 통해 스케줄링하는 것입니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.