Android開源框架Afinal第二篇——庖丁解牛,深入調查


---恢復內容開始---

還是繼續FinalHttp,這個類涉及到的東西還是挺多的。

一:線程池

首先我們看到FinalHttp類里面有兩個跟線程池相關的兩個靜態類

private static final ThreadFactory  sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);
        public Thread newThread(Runnable r) {
            Thread tread = new Thread(r, "FinalHttp #" + mCount.getAndIncrement());
            tread.setPriority(Thread.NORM_PRIORITY - 1);
            return tread;
        }
    };
    
    private static final Executor executor =Executors.newFixedThreadPool(httpThreadCount, sThreadFactory);

ThreadFactory是一個工廠模式,下面是一個線程池Executor。線程池里new出來的線程都是這個ThreadFactory孵化出來的線程,賦予了原始信息線程名字都是FinalHttp #n,(這里還有一個AtomicInteger,這是一個原子操作類,主要用於在高並發環境下的高效程序處理。使用非阻塞算法來實現並發控制。)並且設置線程優先級。

看到這個類里面很多方法都有傳遞這個Executor線程池,沒到執行一個線程我想都是executor 加入線程池去執行的,這樣的線程管理是比較高效和出色的。

二:構造方法

這個構造方法有超多默認配置,蛋疼了米有?

 public FinalHttp() {
        BasicHttpParams httpParams = new BasicHttpParams();

        ConnManagerParams.setTimeout(httpParams, socketTimeout);
        ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections));
        ConnManagerParams.setMaxTotalConnections(httpParams, 10);

        HttpConnectionParams.setSoTimeout(httpParams, socketTimeout);
        HttpConnectionParams.setConnectionTimeout(httpParams, socketTimeout);
        HttpConnectionParams.setTcpNoDelay(httpParams, true);
        HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);

        HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
        ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry);

        httpContext = new SyncBasicHttpContext(new BasicHttpContext());
        httpClient = new DefaultHttpClient(cm, httpParams);
        httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
            public void process(HttpRequest request, HttpContext context) {
                if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
                    request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
                }
                for (String header : clientHeaderMap.keySet()) {
                    request.addHeader(header, clientHeaderMap.get(header));
                }
            }
        });

        httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
            public void process(HttpResponse response, HttpContext context) {
                final HttpEntity entity = response.getEntity();
                if (entity == null) {
                    return;
                }
                final Header encoding = entity.getContentEncoding();
                if (encoding != null) {
                    for (HeaderElement element : encoding.getElements()) {
                        if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
                            response.setEntity(new InflatingEntity(response.getEntity()));
                            break;
                        }
                    }
                }
            }
        });

        httpClient.setHttpRequestRetryHandler(new RetryHandler(maxRetries));

        clientHeaderMap = new HashMap<String, String>();
        
    }

 httpParams是一個網絡鏈接配置類,比如設置最大連接數,路由最大連接數,讀取超時時間,連接超時時間,套接字緩沖大小。這里連接數都是10次,超市時間都是10秒,其實這樣本來就是一種網絡請求任務的拖慢。再下面還有個重復次數,竟然是5次,如果網絡不好的話有可能要重試5次,這樣嚴重影響了上層的UI交互。不過有個亮點就是g-zip,Gzip開啟以后會將輸出的數據進行壓縮的處理,這樣就會減小通過網絡傳輸的數據量,提高讀取的速度。

 

三:AfinalHttp里的方法

1.配置方法:

public void configCharset(String charSet){
        if(charSet!=null && charSet.trim().length()!=0)
            this.charset = charSet;
    }

    public void configCookieStore(CookieStore cookieStore) {
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
    }


    public void configUserAgent(String userAgent) {
        HttpProtocolParams.setUserAgent(this.httpClient.getParams(), userAgent);
    }
    

    /**
     * 設置網絡連接超時時間,默認為10秒鍾
     * @param timeout
     */
    public void configTimeout(int timeout){
        final HttpParams httpParams = this.httpClient.getParams();
        ConnManagerParams.setTimeout(httpParams, timeout);
        HttpConnectionParams.setSoTimeout(httpParams, timeout);
        HttpConnectionParams.setConnectionTimeout(httpParams, timeout);
    }

    /**
     * 設置https請求時  的 SSLSocketFactory
     * @param sslSocketFactory
     */
    public void configSSLSocketFactory(SSLSocketFactory sslSocketFactory) {
        Scheme scheme = new Scheme("https", sslSocketFactory, 443);
        this.httpClient.getConnectionManager().getSchemeRegistry().register(scheme);
    }
    
    /**
     * 配置錯誤重試次數
     * @param retry
     */
    public void configRequestExecutionRetryCount(int count){
        this.httpClient.setHttpRequestRetryHandler(new RetryHandler(count));
    }

這些配置應該都在發起請求之前執行,不過設置超時這個方法太狗血了,竟然三種超時都是10s,那是不是意味着有可能3種超時加起來就要30s,半分鍾啊!

2.請求方法入口,有常用的get()方法,post()方法,download()文件下載方法得各種重載。

那些重載方法這就不貼了,都是調用的HttpHandler類去處理的。

這里我們看到有幾個東西:

AjaxParams,這是一個設置url參數的類。

筆者在實際使用過程中發現,有兩個缺陷。

一個是里頭用到的是ConcurrentHashMap,我們看一看java中幾種常用集合的對比。

Map

HashMap 無序

HashTable:線程安全

LinkedHashMap 有序

ConcurrentHashMap 無序 線程安全

TreeMap:重新排序

 ConcurrentHashMap 是線程安全的,但卻是無序的。適用於高並發情景,但是無序在此就不太恰當。比如有個www.bvin.com/login.jsp?name=bvin&pw=888888,如果用這個Ajax去Put進去的話,有可能會出現像這樣的情況:www.bvin.com/login.jsp?pw=888888&name=bvin,明顯這樣是錯誤的。

還有一點就是,這個類竟然沒有clean()或者removeAll()方法。如果要再次用到這個類的話,就必須重新new一個。其實寫這么個方法就舉手投足的事,AjaxParams里面其實就是兩個ConcurrentHashMap實例。只要把下面這兩個清空就行了。

protected ConcurrentHashMap<String, String> urlParams;
protected ConcurrentHashMap<String, FileWrapper> fileParams;

AjaxCallBack,這是一個泛型抽象類,起回調作用。

   public void onStart(){};
    public void onLoading(long count,long current){};
    public void onSuccess(T t){};
    public void onFailure(Throwable t,String strMsg){};

3.發送請求方法

 protected <T> void sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, AjaxCallBack<T> ajaxCallBack) {
        if(contentType != null) {
            uriRequest.addHeader("Content-Type", contentType);
        }

        new HttpHandler<T>(client, httpContext, ajaxCallBack,charset)
        .executeOnExecutor(executor, uriRequest);

    }
    
    protected Object sendSyncRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType) {
        if(contentType != null) {
            uriRequest.addHeader("Content-Type", contentType);
        }
        return new SyncRequestHandler(client, httpContext,charset).sendRequest(uriRequest);
    }

 

這里涉及到HttpHandler和SyncRequestHandler兩各類,下回分解了。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM