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

来源:互联网 发布:网银软件下载 编辑:程序博客网 时间:2024/05/01 17:34

---恢复内容开始---

还是继续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两各类,下回分解了。。。