Volley源码分析

1. 创建一个请求队列

RequestQueue queue = Volley.newRequestQueue(context)

对应源码分析:

public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
    BasicNetwork network;
    if (stack == null) {
        if (Build.VERSION.SDK_INT >= 9) {
            network = new BasicNetwork(new HurlStack());//[1.1][1.2]生成一个netWork
        } else {
            String userAgent = "volley/0";
            try {
                String packageName = context.getPackageName();
                PackageInfo info =
                        context.getPackageManager().getPackageInfo(packageName, /* flags= */ 0);
                userAgent = packageName + "/" + info.versionCode;
            } catch (NameNotFoundException e) {
            }
            network =
                    new BasicNetwork(
                            new HttpClientStack(AndroidHttpClient.newInstance(userAgent)));
        }
    } else {
        network = new BasicNetwork(stack);
    }
    //[1.3]
    return newRequestQueue(context, network);
}

1.1 生成一个HurlStack

public HurlStack() {
    this(null);
}
public HurlStack(UrlRewriter urlRewriter) {
    this(urlRewriter, null);
}
public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {
    mUrlRewriter = urlRewriter;//null
    mSslSocketFactory = sslSocketFactory;//null
}

1.2 生成BasicNetwork

public BasicNetwork(BaseHttpStack httpStack) {
    this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));//生成4096对应的缓存
}
public BasicNetwork(BaseHttpStack httpStack, ByteArrayPool pool) {
    mBaseHttpStack = httpStack;
    mHttpStack = httpStack;
    mPool = pool;
}

1.3 生成RequestQueue

private static RequestQueue newRequestQueue(Context context, Network network) {
    File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
    //[1.4]生成请求队列
    RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
    //[1.5]执行队列
    queue.start();
    return queue;
}

1.4 生成RequestQueue

public RequestQueue(Cache cache, Network network) {
    this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);//4个线程
}

public RequestQueue(Cache cache, Network network, int threadPoolSize) {
    this(cache,network,threadPoolSize,new ExecutorDelivery(new Handler(Looper.getMainLooper())));
}

public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
    mCache = cache;
    mNetwork = network;
    mDispatchers = new NetworkDispatcher[threadPoolSize];
    mDelivery = delivery;
}

1.4.1 创建一个执行器,用主线程处理

public ExecutorDelivery(final Handler handler) {
    mResponsePoster =
            new Executor() {
                @Override
                public void execute(Runnable command) {
                    handler.post(command);
                }
            };
}

1.5 队列开始执行

public void start() {
    stop();//停止一切任务的派发
    //创建一个缓存派发器[1.6]
    mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
    //[1.7]
    mCacheDispatcher.start();

    //[1.8]
    for (int i = 0; i < mDispatchers.length; i++) {
        NetworkDispatcher networkDispatcher =
                new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
        mDispatchers[i] = networkDispatcher;
        //[1.9]
        networkDispatcher.start();
    }
}

1.6 生成缓存派发器

private final PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<>();
private final PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<>();

//cache是new DiskBasedCache(cacheDir)
//mDelivery是ExecutorDelivery

public CacheDispatcher(
        BlockingQueue<Request<?>> cacheQueue,
        BlockingQueue<Request<?>> networkQueue,
        Cache cache,
        ResponseDelivery delivery) {
    mCacheQueue = cacheQueue;
    mNetworkQueue = networkQueue;
    mCache = cache;
    mDelivery = delivery;
    //请求等待管理
    mWaitingRequestManager = new WaitingRequestManager(this);
}

1.7 开启缓存派发(此时执行的是CacheDispatcher.run())

这段代码可以看出,这个线程中有一个循环进行处理

@Override
public void run() {
    if (DEBUG) VolleyLog.v("start new dispatcher");
    //设置优先级
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

    // Make a blocking call to initialize the cache.
    mCache.initialize();

    while (true) {
        try {
            processRequest();//[1.7.1]
        } catch (InterruptedException e) {
            // We may have been interrupted because it was time to quit.
            if (mQuit) {
                Thread.currentThread().interrupt();
                return;
            }
            VolleyLog.e(
                    "Ignoring spurious interrupt of CacheDispatcher thread; "
                            + "use quit() to terminate it");
        }
    }
}

1.7.1

private void processRequest() throws InterruptedException {
    final Request<?> request = mCacheQueue.take();//一直阻塞在这里直到有请求
    processRequest(request);//处理请求此处是一个大块,所以在#3中讲解
}

1.8 生成NetworkDispatcher

public NetworkDispatcher(
        BlockingQueue<Request<?>> queue,//同1.6中
        Network network,//BasicNetwork
        Cache cache,//DiskBasedCache
        ResponseDelivery delivery/* ExecutorDelivery */) {
    mQueue = queue;
    mNetwork = network;
    mCache = cache;
    mDelivery = delivery;
}

1.9 依旧是一个死循环,对请求进行派发

@Override
public void run() {
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    while (true) {
        try {
            processRequest();
        } catch (InterruptedException e) {
            // We may have been interrupted because it was time to quit.
            if (mQuit) {
                Thread.currentThread().interrupt();
                return;
            }
            VolleyLog.e(
                    "Ignoring spurious interrupt of NetworkDispatcher thread; "
                            + "use quit() to terminate it");
        }
    }
}


private void processRequest() throws InterruptedException {
    Request<?> request = mQueue.take();
    processRequest(request);
}

这里面涉及到两个死循环,一个是缓存队列,一个是网络请求队列。

2. Request的子类

这里写图片描述

图中可以看出Request有这几个子类:

  • ImageRequest
  • MockRequest
  • ClearCacheReques
  • StringRequest

列举一个最简单的StringRequest看看实现:


public class StringRequest extends Request<String> {

    private final Object mLock = new Object();

    @Nullable
    @GuardedBy("mLock")
    private Listener<String> mListener;

    public StringRequest(
            int method,
            String url,
            Listener<String> listener,
            @Nullable ErrorListener errorListener) {
        super(method, url, errorListener);
        mListener = listener;
    }

    public StringRequest(String url, Listener<String> listener, @Nullable ErrorListener errorListener) {
        this(Method.GET, url, listener, errorListener);
    }

    @Override
    public void cancel() {
        super.cancel();
        synchronized (mLock) {
            mListener = null;
        }
    }

    @Override
    protected void deliverResponse(String response) {
        Response.Listener<String> listener;
        synchronized (mLock) {
            listener = mListener;
        }
        if (listener != null) {
            listener.onResponse(response);
        }
    }

    @Override
    @SuppressWarnings("DefaultCharset")
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }
}

这部分代码不多,主要关注deliverResponse()和parseNetworkResponse()方法,首先看出这两个方法是重写的,这两个方法在每一个自定义的Request中都必须重写。

  • deliverResponse(): 响应成功后在这里调用了onResponse()方法
  • parseNetworkResponse(): 可以看出是对response做一些处理,将服务端返回的NetworkResponse转化成自己定义的类型返回,所以这块是处理返回结果的。

3. 请求的添加

请求队列在#1中已经创建完成,接下来的操作就是请求的添加

public <T> Request<T> add(Request<T> request) {
    //设置当前请求属于当前队列
    request.setRequestQueue(this);
    //private final Set<Request<?>> mCurrentRequests = new HashSet<>();
    synchronized (mCurrentRequests) {
        mCurrentRequests.add(request);
    }
    //记录请求的个数
    request.setSequence(getSequenceNumber());
    //添加标记
    request.addMarker("add-to-queue");
    //是否缓存可用,默认可用
    if (!request.shouldCache()) {
        mNetworkQueue.add(request);
        return request;
    }
    //给缓存队列中添加
    mCacheQueue.add(request);
    return request;
}

4. 缓存线程

在1.7中我们触发了缓存线程的启动,所以这里我们详细说明缓存线程具体做的事情

@VisibleForTesting
void processRequest(final Request<?> request) throws InterruptedException {
    //添加标记
    request.addMarker("cache-queue-take");

    //判断这个请求是否被取消,如果被取消则直接使用finish方法干掉这个请求
    if (request.isCanceled()) {
        request.finish("cache-discard-canceled");
        return;
    }

    // 从文件中取出这个请求的结果,如果结果为null,则标记该请求miss,然后看等待队列中是否存在,如果不存在则添加到网络请求队列当中
    Cache.Entry entry = mCache.get(request.getCacheKey());
    if (entry == null) {
        request.addMarker("cache-miss");
        // Cache miss; send off to the network dispatcher.
        if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
            mNetworkQueue.put(request);
        }
        return;
    }

    // 看该请求是否过期,同样标记一下重新请求
    if (entry.isExpired()) {
        request.addMarker("cache-hit-expired");
        request.setCacheEntry(entry);
        if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
            mNetworkQueue.put(request);
        }
        return;
    }

    // 真正发起请求的地方
    //先将响应的结果包装成NetworkResponse,然后调用Request子类的
    //parseNetworkResponse方法解析数据
    request.addMarker("cache-hit");
    Response<?> response =
            request.parseNetworkResponse(
                    new NetworkResponse(entry.data, entry.responseHeaders));
    request.addMarker("cache-hit-parsed");

    //如果缓存不需要立刻刷新则不更新缓存,将结果派发
    if (!entry.refreshNeeded()) {
        // Completely unexpired cache hit. Just deliver the response.
        mDelivery.postResponse(request, response);
    } else {
         //标记立刻刷新
        request.addMarker("cache-hit-refresh-needed");
        //设置缓存的entry
        request.setCacheEntry(entry);
        // Mark the response as intermediate.
        response.intermediate = true;
        //当请求没有在延迟请求队列中时派发结果,派发成功之后则运行该runnable
        if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
            // 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) {
                                // Restore the interrupted status
                                Thread.currentThread().interrupt();
                            }
                        }
                    });
        } else {
            // request has been added to list of waiting requests
            // to receive the network response from the first request once it returns.
            mDelivery.postResponse(request, response);
        }
    }
}

这里写图片描述

5. 请求线程

@VisibleForTesting
void processRequest(Request<?> request) {
    long startTimeMs = SystemClock.elapsedRealtime();
    try {
        //添加请求标记
        request.addMarker("network-queue-take");

        // 按照要求取消请求
        if (request.isCanceled()) {
            request.finish("network-discard-cancelled");
            request.notifyListenerResponseNotUsable();
            return;
        }

        addTrafficStatsTag(request);

        // 实施请求
        NetworkResponse networkResponse = mNetwork.performRequest(request);
        request.addMarker("network-http-complete");

        // If the server returned 304 AND we delivered a response already,
        // we're done -- don't deliver a second identical response.
        if (networkResponse.notModified && request.hasHadResponseDelivered()) {
            request.finish("not-modified");
            request.notifyListenerResponseNotUsable();
            return;
        }

        // 解析请求的返回结果[5.1]
        Response<?> response = request.parseNetworkResponse(networkResponse);
        request.addMarker("network-parse-complete");

        // 如果缓存可用则存入缓存中
        // TODO: Only update cache metadata instead of entire record for 304s.
        if (request.shouldCache() && response.cacheEntry != null) {
            mCache.put(request.getCacheKey(), response.cacheEntry);
            request.addMarker("network-cache-written");
        }

        //标记请求已经发送
        request.markDelivered();
        //对应onResponse,通知使用者
        mDelivery.postResponse(request, response);
        //执行的onResponseReceived,我们可以根据我们自己需求对返回进行处理
        request.notifyListenerResponseReceived(response);
    } catch (VolleyError volleyError) {
        volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
        parseAndDeliverNetworkError(request, volleyError);
        request.notifyListenerResponseNotUsable();
    } catch (Exception e) {
        VolleyLog.e(e, "Unhandled exception %s", e.toString());
        VolleyError volleyError = new VolleyError(e);
        volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
        mDelivery.postError(request, volleyError);
        request.notifyListenerResponseNotUsable();
    }
}

5.1 真正发送请求的处理(BasicNetwork.performRequest())

@Override
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
    long requestStart = SystemClock.elapsedRealtime();
    while (true) {
        HttpResponse httpResponse = null;
        byte[] responseContents = null;
        List<Header> responseHeaders = Collections.emptyList();
        try {
            // Gather headers.
            Map<String, String> additionalRequestHeaders =
                    getCacheHeaders(request.getCacheEntry());
            //在这里调用了mHttpStack的方法[5.2]
            httpResponse = mBaseHttpStack.executeRequest(request, additionalRequestHeaders);
            int statusCode = httpResponse.getStatusCode();

            responseHeaders = httpResponse.getHeaders();
            // Handle cache validation.
            if (statusCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
                ...
            }
                ...
            return new NetworkResponse(
                    statusCode,
                    responseContents,
                    /* notModified= */ false,
                    SystemClock.elapsedRealtime() - requestStart,
                    responseHeaders);
        } catch (SocketTimeoutException e) {
            attemptRetryOnException("socket", request, new TimeoutError());
        } catch (MalformedURLException e) {
            throw new RuntimeException("Bad URL " + request.getUrl(), e);
        } catch (IOException e) {
         ...
        }
    }
}

这里的核心就是通过mHttpStack的performRequest方法,那么mHttpStack是什么呢?根据前面提到过的,这个值是根据不同版本实例化的一个对象,由此可见这里实际调用的是HurlStack.performRequest()方法,方法的内部基本是关于HttpUrlConnection的逻辑代码,这里就不展开说了。可以这么说:HurlStack封装好了HttpUrlConnection,而HttpClientStack封装了HttpClient。该方法返回了httpResponse

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值