美文网首页
Volley源码学习4-BasicNetwork、HttpSta

Volley源码学习4-BasicNetwork、HttpSta

作者: 依然淳熙 | 来源:发表于2017-10-11 15:14 被阅读0次

    BasicNetwork类实现了Network 接口,而Network接口如下:

    package com.android.volley;
    
    /**
     * An interface for performing requests.
     */
    public interface Network {
        /**
         * Performs the specified request.
         * @param request Request to process
         * @return A {@link NetworkResponse} with data and caching metadata; will never be null
         * @throws VolleyError on errors
         */
        NetworkResponse performRequest(Request<?> request) throws VolleyError;
    }
    

    BasicNetwork类在performRequest 将Request发送出去,得到NetworkResponse。看一看BasicNetwork的构造方法如下:

    /**
         * @param httpStack HTTP stack to be used
         * @param pool a buffer pool that improves GC performance in copy operations
         */
        public BasicNetwork(BaseHttpStack httpStack, ByteArrayPool pool) {
            mBaseHttpStack = httpStack;
            // Populate mHttpStack for backwards compatibility, since it is a protected field. However,
            // we won't use it directly here, so clients which don't access it directly won't need to
            // depend on Apache HTTP.
            mHttpStack = httpStack;
            mPool = pool;
        }
    

    实现BasicNetwork 的语句为:

    BasicNetwork network = new BasicNetwork(new HurlStack());
    

    其中 HurlStack 继承了BaseHttpStack 类,而BaseHttpStack类实现了HttpStack接口:

    /**
     * An HTTP stack abstraction.
     *
     * @deprecated This interface should be avoided as it depends on the deprecated Apache HTTP library.
     *     Use {@link BaseHttpStack} to avoid this dependency. This class may be removed in a future
     *     release of Volley.
     */
    @Deprecated
    public interface HttpStack {
        /**
         * Performs an HTTP request with the given parameters.
         *
         * <p>A GET request is sent if request.getPostBody() == null. A POST request is sent otherwise,
         * and the Content-Type header is set to request.getPostBodyContentType().</p>
         *
         * @param request the request to perform
         * @param additionalHeaders additional headers to be sent together with
         *         {@link Request#getHeaders()}
         * @return the HTTP response
         */
        HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError;
    
    }
    

    其实真正进行Http请求访问的是 HurlStack 类,而BasicNetwork 类将其返回的HttpResponse 包装成为NetworkResponse。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. 从request获取请求头
                    Map<String, String> additionalRequestHeaders =
                            getCacheHeaders(request.getCacheEntry());
                    //通过HttpStack对象发送Request得到HttpResponse对象。
                    httpResponse = mBaseHttpStack.executeRequest(request, additionalRequestHeaders);
                    //得到响应状态码
                    int statusCode = httpResponse.getStatusCode();
                    //得到响应头
                    responseHeaders = httpResponse.getHeaders();
                    // Handle cache validation. 当返回状态码为304时,返回状态为304的NetworkResponse对象
                    if (statusCode == HttpURLConnection.HTTP_NOT_MODIFIED) {  //  HTTP 状态码 304:Not Modified。
                        Entry entry = request.getCacheEntry();
                        if (entry == null) {
                            return new NetworkResponse(HttpURLConnection.HTTP_NOT_MODIFIED, null, true,
                                    SystemClock.elapsedRealtime() - requestStart, responseHeaders);
                        }
                        // Combine cached and response headers so the response will be complete.
                        List<Header> combinedHeaders = combineHeaders(responseHeaders, entry);
                        return new NetworkResponse(HttpURLConnection.HTTP_NOT_MODIFIED, entry.data,
                                true, SystemClock.elapsedRealtime() - requestStart, combinedHeaders);
                    }
    
                    // Some responses such as 204s do not have content.  We must check.
                    //获取响应内容存入responseContents
                    InputStream inputStream = httpResponse.getContent();
                    if (inputStream != null) {
                      responseContents =
                              inputStreamToBytes(inputStream, httpResponse.getContentLength());
                    } else {
                      // Add 0 byte response as a way of honestly representing a
                      // no-content request.
                      responseContents = new byte[0];
                    }
    
                    // if the request is slow, log it. 得到请求花费的时间时间
                    long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
                    logSlowRequests(requestLifetime, request, responseContents, statusCode);
                    //如果状态码不正确,抛出异常
                    if (statusCode < 200 || statusCode > 299) {
                        throw new IOException();
                    }
                    //如果一切正确返回 NetworkResponse对象
                    return new NetworkResponse(statusCode, responseContents, 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) {
                    //IOException异常处理
                    int statusCode;
                    if (httpResponse != null) {
                        statusCode = httpResponse.getStatusCode();
                    } else {
                        throw new NoConnectionError(e);
                    }
                    VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
                    NetworkResponse networkResponse;
                    if (responseContents != null) {
                        networkResponse = new NetworkResponse(statusCode, responseContents, false,
                                SystemClock.elapsedRealtime() - requestStart, responseHeaders);
                        if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED ||   //HTTP 状态码 401:Unauthorized。
                                statusCode == HttpURLConnection.HTTP_FORBIDDEN) {  //HTTP 状态码 403:Forbidden。
                            attemptRetryOnException("auth",
                                    request, new AuthFailureError(networkResponse));
                        } else if (statusCode >= 400 && statusCode <= 499) {
                            // Don't retry other client errors.
                            throw new ClientError(networkResponse);
                        } else if (statusCode >= 500 && statusCode <= 599) {
                            if (request.shouldRetryServerErrors()) {
                                attemptRetryOnException("server",
                                        request, new ServerError(networkResponse));
                            } else {
                                throw new ServerError(networkResponse);
                            }
                        } else {
                            // 3xx? No reason to retry.
                            throw new ServerError(networkResponse);
                        }
                    } else {
                        attemptRetryOnException("network", request, new NetworkError());
                    }
                }
            }
        }
    

    接下来来看一看HttpStack类的executeRequest方法:

    @Override
        public HttpResponse executeRequest(Request<?> request, Map<String, String> additionalHeaders)
                throws IOException, AuthFailureError {
            String url = request.getUrl();
            HashMap<String, String> map = new HashMap<>();
            map.putAll(request.getHeaders());
            map.putAll(additionalHeaders);
            if (mUrlRewriter != null) {
                String rewritten = mUrlRewriter.rewriteUrl(url);
                if (rewritten == null) {
                    throw new IOException("URL blocked by rewriter: " + url);
                }
                url = rewritten;
            }
            /**
             * 通过在 URL 上调用 openConnection 方法创建连接对象。
               处理设置参数和一般请求属性。
               使用 connect 方法建立到远程对象的实际连接。
               远程对象变为可用。远程对象的头字段和内容变为可访问。
             */
            URL parsedUrl = new URL(url);
            //调用Url的openConnection 方法得到HttpURLConnection连接对象
            HttpURLConnection connection = openConnection(parsedUrl, request);
            //添加请求头
            for (String headerName : map.keySet()) {
                connection.addRequestProperty(headerName, map.get(headerName));
            }
            //设置请求方法和请求参数
            setConnectionParametersForRequest(connection, request);
            // Initialize HttpResponse with data from the HttpURLConnection.
            //得到响应状态码
            int responseCode = connection.getResponseCode();
            if (responseCode == -1) {
                // -1 is returned by getResponseCode() if the response code could not be retrieved.
                // Signal to the caller that something was wrong with the connection.
                throw new IOException("Could not retrieve response code from HttpUrlConnection.");
            }
            //如果没有响应body
            if (!hasResponseBody(request.getMethod(), responseCode)) {
                return new HttpResponse(responseCode, convertHeaders(connection.getHeaderFields()));
            }
           //如果有响应body
            return new HttpResponse(responseCode, convertHeaders(connection.getHeaderFields()),
                    connection.getContentLength(), inputStreamFromConnection(connection));
        }
    
    
    
    /**
         * Opens an {@link HttpURLConnection} with parameters.
         * @param url
         * @return an open connection
         * @throws IOException
         */
        private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {
            HttpURLConnection connection = createConnection(url);
    
            int timeoutMs = request.getTimeoutMs();
            connection.setConnectTimeout(timeoutMs);
            connection.setReadTimeout(timeoutMs);
            connection.setUseCaches(false);
            connection.setDoInput(true);
    
            // use caller-provided custom SslSocketFactory, if any, for HTTPS
            if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {
                ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
            }
    
            return connection;
        }
    
    /**
         * Create an {@link HttpURLConnection} for the specified {@code url}.
         */
        protected HttpURLConnection createConnection(URL url) throws IOException {
            //每次调用此 URL 的协议处理程序的 openConnection 方法都打开一个新的连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    
            // Workaround for the M release HttpURLConnection not observing the
            // HttpURLConnection.setFollowRedirects() property.
            // https://code.google.com/p/android/issues/detail?id=194495
            connection.setInstanceFollowRedirects(HttpURLConnection.getFollowRedirects());
    
            return connection;
        }
    

    这样就将HttpResponse 返回到了BasicNetwork。

    相关文章

      网友评论

          本文标题:Volley源码学习4-BasicNetwork、HttpSta

          本文链接:https://www.haomeiwen.com/subject/hsoiyxtx.html