一.说明   

      虽说现在网络层框架很多,比如volley,nohttp,okhttp等等,但是目前okhttp还是用的最多的。所以说详细的了解okhttp的使用,

源码解析和okhttp的封装是十分必要的,这一系列文章将从okhttp的使用开始

        OKHttp是Android版Http客户端。非常高效,支持SPDY、连接池、GZIP和 HTTP 缓存。默认情况下,OKHttp会自动处理常见的网络问题,像二次连接、SSL的握手问题。如果你的应用程序中集成了OKHttp,Retrofit默认会使用OKHttp处理其他网络层请求。另外

从Android4.4开始HttpURLConnection的底层实现采用的是okHttp。


   二.使用   

   1.安装


      gradle:

compile 'com.squareup.okhttp:okhttp:2.4.0'
    compile 'com.squareup.okio:okio:1.5.0'

    2.Http Get请求


//创建OkHttp请求对象
    OkHttpClient client = new OkHttpClient(); 
    //每一次网络请求都是一个Request,Request.Builder传入url,header,params,method等信息
    Request request = new Request.Builder().url(url).build();
    //通过request封装一个Call对象,将请求封装成任务,既然是个任务就有execute()和cancel()等方法
    Call call=client.newCall(request);
    //然后直接execute执行得到Response对象,这个方法是个阻塞的方法,通过Response可以得到code,message等信息。
    Response response = call.execute();    
    if (response.isSuccessful()) {     
       boolean fromCache = response.cacheResponse() != null;
       return response.body().string();
    } else {        
       throw new IOException("Unexpected code " + response);
    }


     上面是同步的方式,异步的如下


//请求加入调度
    call.enqueue(new Callback()
        {
            @Override
            public void onFailure(Request request, IOException e)
            {
            }
            @Override
            public void onResponse(final Response response) throws IOException
            {
                    //String htmlStr =  response.body().string();
                    //InputStream is=response.body().byteStream();
            }
    });


       onResponse执行的线程是不是ui线程,如果要操作控件,还需要通过handler

      

3.Post请求
   
上面对OkHttp的Get请求分析完之后,OkHttp的整个请求流程和处理流程就清晰,Post请求和Get请求的流程都是一样,区别只是在于Request对象构造上有区别。     (1)Post提交键值对


RequestBody body = new FormEncodingBuilder()
    .add("platform", "android")
    .add("name", "bug")
    .add("subject", "XXXXXXXXXXXXXXX")
    .build();
   
      Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  client.newCall(request).enqueue(new Callback(){});



(2)Post提交json


public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
  OkHttpClient client = new OkHttpClient();
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
    .url(url)
    .post(body)
    .build();
  client.newCall(request).enqueue(new Callback(){})



(3)基于http的文件上传

  

File file = new File(Environment.getExternalStorageDirectory(), "balabala.mp4");
   RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
   RequestBody requestBody = new MultipartBuilder()
     .type(MultipartBuilder.FORM)
     .addPart(Headers.of(
         "Content-Disposition", 
         "form-data; name=\"mFile\"; 
         filename=\"wjd.mp4\""), fileBody)
     .build();
   
   Request request = new Request.Builder()
    .url("http://192.168.1.103:8080/okHttpServer/fileUpload")
    .post(requestBody);
    .build();
    
    Call call = mOkHttpClient.newCall(request);
    call.enqueue(new Callback()
    {
      //...
   });



    通过MultipartBuilder的addPart方法可以添加键值对或者文件。  


  4.编码问题



   在OkHttp中,无论是Get请求还是Post请求所有参数的编码方式都是默认采用UTF-8的编码方式进行编码。

   所以在进行Get请求或Post请求时,文本参数都不需要我们进行手动编码,但是在服务端进行参数解析时,需要做简单的处理,这里我只说明tomcat下运行的Java后台服务的处理方式:

 1.针对Get请求,我们只需要在tomcat的server.xml文件中设置默认编码方式(URIEncoding="UTF-8" )为UTF-8即可,注意此编码设置只对Get请求有效。

  2.针对Post请求,我们在解析获取参数值之前需要手动设置请求的编码方式为UTF-8,如:req.setCharacterEncoding("UTF-8");


  5.取消一个call

    
使用Call.cancel()可以立即停止掉一个正在执行的call。如果一个线程正在写请求或者读响应,将会引发IOException。
 当call没有必要的时候,使用这个api可以节约网络资源。例如当用户离开一个应用时。不管同步还是异步的call都可以取消。
 
   使用Request.Builder.tag(tag)来分配一个标签。之后你就可以用OkHttpClient.cancel(tag)来取消所有带有这个tag的call

  



6.设置连接和读写时间,cookie的持久化保存,https的支持,


<span style="font-family:SimSun;"> //cookie信息的持久化保存
        CookieHandler cookieHandler = new CookieManager(new PersistentCookieStore(context),
                CookiePolicy.ACCEPT_ALL);
        //Interceptor是拦截器, 在发送之前, 添加一些参数, 或者获取一些信息.loggingInterceptor是打印参数
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        
        //设置缓存的文件        
        File httpCacheDirectory = new File(context.getExternalCacheDir(), "xxx");
        //设置可访问所有的https网站,可以把第一个参数改成具体网站证书的inputstream,比如getAssets().open("xx");
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);
        
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                //设置网络超时
                .readTimeout(7676, TimeUnit.MILLISECONDS)
                .connectTimeout(7676,TimeUnit.MILLISECONDS)
                //设置拦截器来打印网络请求的返回结果
                .addInterceptor(logging)
                .cookieJar(new JavaNetCookieJar(cookieHandler))
                //开启okHttp缓存
                .setCache(new Cache(httpCacheDirectory,10 * 1024 * 1024));
                //对https网站的支持
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager))
                //通过设置拦截器的方式来addHeader
                .addInterceptor(new Interceptor() {
              
             @Override
           public Response intercept(Chain chain) throws IOException {
              Request request = chain.request()
               .newBuilder()
               .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
               .addHeader("Accept-Encoding", "gzip, deflate")
               .addHeader("Connection", "keep-alive")
               .addHeader("Accept", "*/*")
               .addHeader("Cookie", "add cookies here")
               .build();
               return chain.proceed(request);
              }
            }))
            .build();</span>

     


okhttp的官方不建议创建多个OkHttpClient对象 ,我们在项目中使用肯定要自己做封装,或者使用别人的封装框架。在后面我也会试着去自己封装一个全能的OkHttpUtils框架,这需要时间