zoukankan      html  css  js  c++  java
  • 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两各类,下回分解了。。。

  • 相关阅读:
    20200804 千锤百炼软工人第三十天
    20200803 千锤百炼软工人第二十九天
    20200802 千锤百炼软工人第二十八天
    小谢第51问:从输入url到浏览器显示页面发生了什么
    小谢第50问:vuex的五个属性-使用-介绍
    小谢第49问:URL都由什么组成
    小谢第48问:js跳转页面与打开新窗口的方法
    小谢第47问:vue项目中,assets和static的区别
    小谢第46问:js事件机制
    小谢第45问:Ajax 是什么? 如何创建一个 Ajax
  • 原文地址:https://www.cnblogs.com/bvin/p/3113870.html
Copyright © 2011-2022 走看看