美文网首页
6.1开源框架-okhttp网络框架-详解

6.1开源框架-okhttp网络框架-详解

作者: 205蚁 | 来源:发表于2018-11-18 16:21 被阅读0次

    okhttp网络框架

      1. OkHttp使用简介
      1. OkHttp源码剖析

    1.OkHttp使用简介




      1. 创建客户端
        OkhttpClient client = new OkHttpClient();//作为单例,这样所有的请求可以公共response缓存和线程池
      1. 创建Request对象
        Request request = new Request.Builder().url("http://xxx").build();
        图上:封装了Http的一些请求信息
        Builder模式构建,builder模式会将它的显示和创建所分离
      1. 创建Call对象,call对象就是一个Http请求,execute开始执行
        okttp3.Response response = client.newCall(request).execute();
        //其中Call是连接request和Response的的桥梁
        Call对象既可以同步获取时间,也可以异步获取获取
         //同步获取方法   
        if(!response.isSuccessful())
            throw new IOException("Unexpected code "+response);
            
        Headers responseHeaders = response.headers()
        for(int i=0;i<responseHeaders.size();i++){
            System.out.println(responseHeaders.name(i)+": "+responseHeaders.value(i));
        }
        System.out.println(response.body().string());
    

    同步获取数据它会阻塞当前线程去请求数据,返回response对象给线程.response也会包含状态码,响应头,响应body

        //异步获取方法:
        //前两步一样:
        client.newCall(request).enqueue(new Callback(){
            public void onFailure(Call call,IOException e){
                e.printStackTrace();
            }
            public void onResponse(Call call,okhttp3.Response response) throws IOExcepiton{
                if(!response.isSuccessful())
                    throw new IOException("Unexpected code "+response);
                Headers responseHeaders = response.headers();
                for(int i=0;i<responseHeaders.size();i++){
                    System.out.println(responseHeaders.name(i)+": "+responseHeaders.value(i));
                }
                System.out.println(response.body().string());
            }
        })
    

    enqueue方法不会阻塞当前进程,会开启子线程,网络请求在子线程操作,当请求结束后,会回调成功、失败(在工作线程中执行)

    2.OkHttp源码剖析

    图:



    7-1 okhttp网络框架面[00_06_58][20180721-155323-5].jpg
    1. Application
    2.Application INTERCEPTORS 包括↓request ↑response
    OkHttp core

    1.↓CACHE ↑CACHE 2.NETWORK INTERCEPTORS ↓request ↑response

      1. 创建客户端
        OkhttpClient client = new OkHttpClient();
    • 2.创建Request对象
      Request request = new Request.Builder().url("http://xxx").build();
      //builder模式的作用就是将一个复杂对象的构建与他的表示像分离,这样就可以是同样的构建过程创建不同的的表示
    • 3.okttp3.Response response = client.newCall(request).execute();
      • newCall()里面是 return new RealCall(this.request,false);
            RealCall类中方法;
            public Response execute()throw IOException {
                synchronized(this){
                //检查
                if(executed) throw new IllegalStateException("Already Executed")
                executed = true;
                }
                //每个call只能执行一次,如果想要一个完全的方法,可以使用call.clone方法
                captureCallStackTrace();
                try{
                    client.dispatcher().executed(this);//开始同步请求
                    //dispatcher官方文档中它是一个异步请求的策略,但是它也能做一些同步请求的操作
                    Response result = getResponseWithInterceptorChain();
                    //okhttp最精髓的地方,拦截器。经过拦截器拦截后,会返回一个response结果给我们的http
                    if(result = null) throw new IOException("Canceled");
                    return result;
                }finally{
                    client.dispathcher().finished(this);
                    //通知我们的dispatcher 任务完成
                }
            }
    
            //以下finished的源码
                finished(runningSyncCalls,call,false);
                即
                private <T> void finished(Deque<T> calls,T call,boolean promoteCalls){
                    int runningCallsCount;
                    Runnable idleCallback;
                    synchronized(this){
                        if(!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
                        if(promoteCalls) promoteCalls();
                        runningCallsCount = runningCallsCount();
                        idleCallback = this.idleCallback;
                    }
                    if(runningCallsCount == 0 && idleCallback !=null){
                        idleCallback.run();
                    }
                }
    

    //做的工作:把请求队列关闭
    在同步操作中,client.dispatcher().executed(this)中涉及到dispatcher并不是真正的去做异步操作,只是告诉我们执行的状态。开始执行时executed,执行完了finished方法

    真正做网络请求并返回结果的是方法getResponseWithInterceptorChain();

            Response getResponseWithInterceptorChain() throw IOExption{
                List<Interceptor> interceptors = new ArrayList<>();
                interceptors.addAll(client.interceptors);
                interceptors.add(retryAndrFollowUpInterceptor);
                interceptors.add(new BirdgeInterceptor(client.cookieJar()));
                interceptors.add(new CacheInterceptor(client.internalCache()));
                interceptors.add(new ConnectInterceptor(client));
                
                if(!forWebSocket){
                    interceptors.addAll(client.networkInterceptors());
                }
                interceptors.add(new CallServerInterceptor(forWebSocket));
                Intercepor.Chain chain = new RealInterceptorChain(interceptors,null,null,null,0,originalRequest);
                return chain.proceed(originalRequest);
            }
    

    interceptor 它把网络请求缓存,压缩等所有功能都统一起来,每一个都是interceptor,连接起来成了一个interceptor.chain

    • 各拦截器
      retryAndrFollowUpInterceptor -->失败重试,重定向,重定向另外一个url
      BirdgeInterceptor 为了把用户构造的请求转换成发送到服务器的请求,然后把服务器的响应转回给用户,进行一些友好输出的响应,这是一个桥接的interceptor
      CacheInterceptor :缓存拦截器,读取,更新缓存
      ConnectInterceptor :和服务端进行连接的拦截器
      CallServerInterceptor :网络的服务器端的连接
            具体分析一个拦截器:
                CallServerInterceptor
                类结构
                +boolean forWebSocket:构造赋值
                --------------------
                public Response intercept(Chain chain) throws IOExcetion{
                    
                }
    
    • 主要作用,向服务器发送一个头部,如果有body也会发送。发送之后获取response的头部和body
    • 其中httpCodec.writeRequestHeaders(request),需要关注httpCodec它的内部是Okio对象 ,okio封装了socket;
    • interceptor设计是一个分层的思想,每一个interceptor就是一层,这是tcp/ip协议是异曲同工之秒、
    • 每一层简化了,每一层只关心每一层的事情,比如CallServerInterceptor只关心和服务器的连接;
      把各种复杂的任务拆分成一个一个独立的任务,这样对以后的拓展很有帮助。

    异步请求源码分析

            enqueue也是在RealCall里面处理的
            public void enqueue(Callback responseCallback){
                //同上检查是否已执行
                captureCallStackTrace();
                client.dispatcher().enqueue(new AsyncCall(responseCallback));
            }
            
            Dispatcher 的enqueue方法:
            synchronized void enqueue(AsyncCall call){
                if(runningAsyncCalls.size()<maxREquests && runningCallsForHost(call) < maxRequestsPerHost){
                    runningAsyncCalls.add(call);//满足要求添加到队列里面
                    executorService().execute(call);
                }else{
                    readyAsyncCalls.add(call);
                }
            }
            
    

    类中有是三个集合

            Dequeue<AsyncCall> readyAsyncCalls = new ArrayQeueue<>();//正在准备的异步请求
            Dequeue<AsyncCall> runningAsyncCalls = new ArrayQeueue<>();
            //正在运行的异步请求
            Dequeue<AsyncCall> runningSyncCalls  = new ArrayQeueue<>();//
            //正在运行的同步请求
            executorService() 返回一个线程池(java当中的一个并发类)
                if(executorService == null){
                    executorService = new ThreadPoolExecutor(0,Integer.MAIN_VALUE,60,TimeUnit.SECONDS,NEW SynchronourQueue<Runnable>(),Util.threadFactory("OkHttp Dispatcher",false));
                }
                return executorService;
    

    总结

    相关文章

      网友评论

          本文标题:6.1开源框架-okhttp网络框架-详解

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