开发者社区> 优惠码发放> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Android之OkHttp详解

简介: Android之OkHttp详解文章大纲一、OkHttp简介二、OkHttp简单使用三、OkHttp封装四、项目源码下载 一、OkHttp简介 什么是OkHttp  一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发送 HTTP 请求,并对响应进行处理。
+关注继续查看

Android之OkHttp详解
文章大纲
一、OkHttp简介
二、OkHttp简单使用
三、OkHttp封装
四、项目源码下载

一、OkHttp简介

  1. 什么是OkHttp
      一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发送 HTTP 请求,并对响应进行处理。比如可以使用http客户端与第三方服务(如SSO服务)进行集成,当然还可以爬取网上的数据等。OKHttp与HttpClient类似,也是一个Http客户端,提供了对 HTTP/2 和 SPDY 的支持,并提供了连接池,GZIP 压缩和 HTTP 响应缓存功能。
  2. OkHttp优点
    (1)支持HTTP2/SPDY(SPDY是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验)

(2)socket自动选择最好路线,并支持自动重连,拥有自动维护的socket连接池,减少握手次数,减少了请求延迟,共享Socket,减少对服务器的请求次数
(3)基于Headers的缓存策略减少重复的网络请求
(4)拥有Interceptors轻松处理请求与响应(自动处理GZip压缩)

  1. OkHttp功能
    (1)一般的get请求

(2)一般的post请求
(3)基于Http的文件上传
(4)文件下载
(5)上传下载的进度回调
(6)加载图片
(7)支持请求回调,直接返回对象、对象集合
(8)支持session的保持
(9)支持自签名网站https的访问,提供方法设置下证书就行
(10)支持取消某个请求

  1. OkHttp使用步骤
    (1)get请求的步骤,首先构造一个Request对象,参数最起码有个url,当然你可以通过Request.Builder设置更多的参数比如:header、method等。

(2)然后通过request的对象去构造得到一个Call对象,类似于将你的请求封装成了任务,既然是任务,就会有execute()和cancel()等方法。
(3)最后,我们希望以异步的方式去执行请求,所以我们调用的是call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。
(4)onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,
可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()
(5)看到这,你可能会奇怪,竟然还能拿到返回的inputStream,看到这个最起码能意识到一点,这里支持大文件下载,有inputStream我们就可以通过IO的方式写文件。不过也说明一个问题,这个onResponse执行的线程并不是UI线程。的确是的,如果你希望操作控件,还是需要使用handler等
(6)okHttp还支持GJson的处理方式
(7)okhttp支持同步请求和异步请求,Call call = client.newCall(request);为同步请求,发送请求后,就会进入阻塞状态,知道收到响应call.enqueue(new Callback()为异步请求
(8)在okhttp3.Callback的回调方法里面有个参数是Call 这个call可以单独取消相应的请求,随便在onFailure或者onResponse方法内部执行call.cancel()都可以。如果想取消所有的请求,则可以okhttpclient.dispatcher().cancelAll();

二、OkHttp简单使用

  1. 进行get请求
    /**

    • 原始的get请求
    • @author 吴晓畅
      *

*/
public class OkHttpGet {


public void get() {
    
     //1.okhttpClient对象
    OkHttpClient okHttpClient = new OkHttpClient.Builder().
            //在这里,还可以设置数据缓存等
            //设置超时时间
            connectTimeout(15, TimeUnit.SECONDS).
            readTimeout(20, TimeUnit.SECONDS).
            writeTimeout(20,  TimeUnit.SECONDS).
            //错误重连  
            retryOnConnectionFailure(true).
            build();
    
    //2构造Request,
    //builder.get()代表的是get请求,url方法里面放的参数是一个网络地址
    Request.Builder builder = new Request.Builder();
    
    Request request = builder.get().url("http://www.baidu.com/").build();

    //3将Request封装成call
    Call call = okHttpClient.newCall(request);
    
    //4,执行call,这个方法是异步请求数据
    call.enqueue(new Callback() {
        
        @Override
        public void onFailure(Call arg0, IOException arg1) {
            
            //失败调用
        }

        @Override
        //由于OkHttp在解析response的时候依靠的是response头信息当中的Content-Type字段来判断解码方式
        //OkHttp会使用默认的UTF-8编码方式来解码
        //这里使用的是异步加载,如果需要使用控件,则在主线程中调用
        public void onResponse(Call arg0, Response arg1) throws IOException {
            
             //成功调用
            
        }
    });
    
}

}

  1. 进行post请求
    /**

    • 使用okhttp进行post请求
    • @author 吴晓畅
      *

*/
public class OkHttpPost {


public void initPost() {
    
    //1.okhttpClient对象
    OkHttpClient okHttpClient = new OkHttpClient.Builder().
            //在这里,还可以设置数据缓存等
            //设置超时时间
            connectTimeout(15, TimeUnit.SECONDS).
            readTimeout(20, TimeUnit.SECONDS).
            writeTimeout(20,  TimeUnit.SECONDS).
            //错误重连  
            retryOnConnectionFailure(true).
            build();
    
     RequestBody requestBodyPost = new FormBody.Builder()
     .add("page", "1")
     .add("code", "news")
     .add("pageSize", "20")
     .add("parentid", "0")
     .add("type", "1")
     .build();
     
     Request requestPost = new Request.Builder()
     .url("www.baidu.com")
     .post(requestBodyPost)
     .build();
     
     okHttpClient.newCall(requestPost).enqueue(new Callback() {

        @Override
        public void onFailure(Call arg0, IOException arg1) {
            // TODO Auto-generated method stub
            
        }

        @Override
        public void onResponse(Call arg0, Response arg1) throws IOException {
            
            //okHttp还支持GJson的处理方式
            //在这里可以进行List<bean>和bean处理
            
        }
         
     });
      
      

}

}

  1. 进行图片上传和下载
    /**

    • 使用OkHttp进行图片上传和下载
    • @author 吴晓畅
      *

*/
public class OkHttpPicture
{

public void getPicture() {
    
     //1.创建一个okhttpclient对象  
     OkHttpClient okHttpClient = new OkHttpClient();  
     
     //2.创建Request.Builder对象,设置参数,请求方式如果是Get,就不用设置,默认就是Get  
     Request request = new Request.Builder()  
            .url("www.baidu.com")  
            .build();  
     
     //3.创建一个Call对象,参数是request对象,发送请求  
     Call call = okHttpClient.newCall(request);  
     
     //4.异步请求,请求加入调度  
     call.enqueue(new Callback() {

        @Override
        public void onFailure(Call arg0, IOException arg1) {
            // TODO Auto-generated method stub
            
        }

        @Override
        public void onResponse(Call arg0, Response arg1) throws IOException {
            

// //得到从网上获取资源,转换成我们想要的类型
// byte[] Picture_bt = response.body().bytes();
// //通过handler更新UI
// Message message = handler.obtainMessage();
// message.obj = Picture_bt;
// message.what = SUCCESS;
// handler.sendMessage(message);

            
        } 
         
         
         
    });  

}

public void shangChuanPicture() {
    
    OkHttpClient mOkHttpClent = new OkHttpClient();
    
    //获取sd卡中的文件
    File file = new File(Environment.getExternalStorageDirectory()+"/HeadPortrait.jpg");
    
    
    MultipartBody.Builder builder = new MultipartBody.Builder()
            //设置类型
            .setType(MultipartBody.FORM)
            //设置正文内容
            .addFormDataPart("img", "HeadPortrait.jpg",
                    RequestBody.create(MediaType.parse("image/png"), file));

    RequestBody requestBody = builder.build();

    Request request = new Request.Builder()
            .url("www.baidu.com")
            .post(requestBody)
            .build();
    
    Call call = mOkHttpClent.newCall(request);

}

}

  1. 拦截器使用
    什么是拦截器

  首先我们需要了解什么事拦截器。打个比方,镖局押着一箱元宝在行走在一个山间小路上,突然从山上下来一群山贼拦住了镖局的去路,将镖局身上值钱的东西搜刮干净后将其放行。其中山贼相当于拦截器,镖局相当于一个正在执行任务的网络请求,请求中的参数就是镖局携带的元宝。拦截器可以将网络请求携带的参数进行修改验证,然后放行。这里面其实设计了AOP编程的思想(面向切面编程)。
  在介绍拦截器的作用和好处之前,我们还是要回到山贼这个角色上,如果让你做一次山贼,你会在什么地方埋伏?肯定是在镖局必经之路上埋伏。也就是说,拦截器就是在所有的网络请求的必经之地上进行拦截。
(1)拦截器可以一次性对所有的请求和返回值进行修改。
(2)拦截器可以一次性对请求的参数和返回的结果进行编码,比如统一设置为UTF-8.
(3)拦截器可以对所有的请求做统一的日志记录,不需要在每个请求开始或者结束的位置都添加一个日志操作。
(4)其他需要对请求和返回进行统一处理的需求….

OkHttp中拦截器分类
OkHttp中的拦截器分2个:APP层面的拦截器(Application Interception)、网络请求层面的拦截器(Network Interception)
(1)Application Interceptor是在请求执行刚开始,还没有执行OkHttp的核心代码前进行拦截,Application拦截器的作用:
1)不需要担心是否影响OKHttp的请求策略和请求速度。
2)即使是从缓存中取数据,也会执行Application拦截器。
3)允许重试,即Chain.proceed()可以执行多次。(当然请不要盲目执行多次,需要加入你的逻辑判断)
(2)Network Interception是在连接网络之前
1)可以修改OkHttp框架自动添加的一些属性(当然最好不要修改)。
2)可以观察最终完整的请求参数(也就是最终服务器接收到的请求数据和熟悉)

使用注意点
如果对拦截器不是很熟的同学,开发过程中,建议使用Application Interception。这样避免对OkHttp请求策略的破坏。

常见实际场景
(1)对请求参数进行统一加密处理。
(2)拦截不符合规则的URL。
(3)对请求或者返回参数设置统一的编码方式
(4)其它…。

代码实操

public class OkHttpLanJieQi {


/**
 * 应用拦截器
 */
Interceptor appInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        
        Request request = chain.request();
        
        //———请求之前要做的事情————
        HttpUrl url = request.url();
        String s = url.url().toString();
        
        Response response = chain.proceed(request);
        
        //———请求之后要做事情————
        Log.d("aa","app interceptor:begin");
        
        return response;
        
    }

};

/**
 * 网络拦截器
 */
Interceptor networkInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        
        //———请求之前要做的事情————
        
        Response  response = chain.proceed(request);
        
      //———请求之后要做事情————
        
        return response;
    }
};

/**
 * 进行get请求,并配置拦截器
 */
public void initGet() {
    
    OkHttpClient okHttpClient = new OkHttpClient
            .Builder()
            .addInterceptor(appInterceptor)//Application拦截器
            .addNetworkInterceptor(networkInterceptor)//Network拦截器
            .build();
    
    //2构造Request,
    //builder.get()代表的是get请求,url方法里面放的参数是一个网络地址
    Request.Builder builder = new Request.Builder();
    
    Request request = builder.get().url("http://www.baidu.com/").build();

    //3将Request封装成call
    Call call = okHttpClient.newCall(request);
    
    //4,执行call,这个方法是异步请求数据
    call.enqueue(new Callback() {
        
        @Override
        public void onFailure(Call arg0, IOException arg1) {
            
            //失败调用
        }

        @Override
        //由于OkHttp在解析response的时候依靠的是response头信息当中的Content-Type字段来判断解码方式
        //OkHttp会使用默认的UTF-8编码方式来解码
        //这里使用的是异步加载,如果需要使用控件,则在主线程中调用
        public void onResponse(Call arg0, Response arg1) throws IOException {
            
             //成功调用
            
        }
    });
}

}
三、OkHttp封装

  1. 自行简单封装
    /**

    • okhttp操作进行封装
    • @author 吴晓畅
      *

*/
public class OkHttp {



public void get(String url, Callback callback) {
    
    //1.okhttpClient对象
    OkHttpClient okHttpClient = new OkHttpClient.Builder().
            //在这里,还可以设置数据缓存等
            //设置超时时间
            connectTimeout(15, TimeUnit.SECONDS).
            readTimeout(20, TimeUnit.SECONDS).
            writeTimeout(20,  TimeUnit.SECONDS).
            addInterceptor(appInterceptor).//Application拦截器
            //错误重连  
            retryOnConnectionFailure(true).
            build();
    
    //2构造Request,
    //builder.get()代表的是get请求,url方法里面放的参数是一个网络地址
    Request.Builder builder = new Request.Builder();
    
    Request request = builder.get().url(url).build();
    
    //3将Request封装成call
    Call call = okHttpClient.newCall(request);
    
    //4,执行call,这个方法是异步请求数据
    call.enqueue(callback);
    
}

public void post(String url, List<String> list, Callback callback, RequestBody requestBody) {
    
    //1.okhttpClient对象
    OkHttpClient okHttpClient = new OkHttpClient.Builder().
            //在这里,还可以设置数据缓存等
            //设置超时时间
            connectTimeout(15, TimeUnit.SECONDS).
            addInterceptor(appInterceptor).//Application拦截器
            readTimeout(20, TimeUnit.SECONDS).
            writeTimeout(20,  TimeUnit.SECONDS).
            //错误重连  
            retryOnConnectionFailure(true).
            build();
    
     RequestBody requestBodyPost = requestBody;
     
     Request requestPost = new Request.Builder()
     .url(url)
     .post(requestBodyPost)
     .build();
     
     okHttpClient.newCall(requestPost).enqueue(callback);

}

/**
 * 应用拦截器
 */
Interceptor appInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        
        Request request = chain.request();
        
        //———请求之前要做的事情————

        Response response = chain.proceed(request);
        
        //———请求之后要做事情————
        
        return response;
        
    }

};

}

  1. Android--OKHttpUtils框架封装
    简介

  OKHttpUtils:一个专注于让网络请求更简单的网络请求框架,对于任何形式的网络请求只需要一行代码。它是OKHttp的一次二次封装,封装的目的是让网络请求更加方便。

OKHttpUtils优势
(1)性能高,使用主流的okhttp的进行封装
  OKHttp我们知道它支持http2和socket的重连。自动选择最好的路线,拥有自己维护socket维护的连接池。可以减少TCP的握手次数,同时它拥有队列线程池可以轻松的并发请求。
(2)特有的网络缓存模式
  OKHttpUtils是大多数网络框架不具备的,比如我们公司的网络老板要求不仅在有网的情况下,进行展示网络数据,在无网的情况下使用缓存数据。这时候我们使用普通网络请求,就需要大量的判断。当前是否有网和无网状态,根据不同的状态保存不同的数据。然后再决定是否使用缓存。但是这是一个通用的写法。于是OKHttpUtils使用自动网络缓存模式。让用户只关注数据处理。
(3)方便易用的扩展接口
  可以添加全局的公共参数、全局的拦截器、全局的超时时间,更可以对单个请求定制拦截器。请求参数修改等等。
(4)强大的Cookie的保存策略
  在客户端对Cookie的获取不是一个特别简单的事情,Cookie全程自动管理,并且提供了额外的Cookie管理方法,引入额外的自动管理中,添加任何你想创建的Cookie。

依赖包导入

compile 'com.zhy:okhttputils:2.0.0'
进行get请求

private String get(String url) throws IOException {
    
  Request request = new Request.Builder()
  
      .url(url)//传url
      
      .build();//创建

  //把request传进client
  //execute()执行线程
  Response response = client.newCall(request).execute();
  
  return response.body().string();
}

进行post请求

private String post(String url, String json) throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder()
        .url(url)
        .post(body)
        .build();
    Response response = client.newCall(request).execute();
    return response.body().string();
}

使用okhttp-utils请求单张图片

public void getImage()

    {
     tv_result.setText("");
        String url = "http://images.csdn.net/20150817/1.jpg";
        OkHttpUtils
                .get()//
                .url(url)//
                .tag(this)//
                .build()//
                .connTimeOut(20000)//链接超时
                .readTimeOut(20000)//读取超时
                .writeTimeOut(20000)//写入超时
                .execute(new BitmapCallback()
                {
                    @Override
                    public void onError(Call call, Exception e, int id)
                    {
                        tv_result.setText("onError:" + e.getMessage());
                    }

                    @Override
                    public void onResponse(Bitmap bitmap, int id)
                    {
                        Log.e("TAG", "onResponse:complete");
                        iv_icon.setImageBitmap(bitmap);
                    }
                });
    }

使用okhttp-utils上传多个或者单个文件

/**

  * 使用okhttp-utils上传多个或者单个文件
  */     
 public void multiFileUpload()
    {
     
     //FileUploadServlet
     String mBaseUrl = "http://192.168.3.27:8080/FileUpload/FileUploadServlet";
     
        File file = new File(Environment.getExternalStorageDirectory(), "tupian.jpg");
        File file2 = new File(Environment.getExternalStorageDirectory(), "zanghao.jpg");
        if (!file.exists())
        {
            Toast.makeText(OKHttpActivity.this, "文件不存在,请修改文件路径", Toast.LENGTH_SHORT).show();
            return;
        }

// Map params = new HashMap();
// params.put("username", "黄敏莹");
// params.put("password", "123");

        String url = mBaseUrl;
        OkHttpUtils.post()//
                .addFile("mFile", "server_tupian.jpg", file)//
                .addFile("mFile", "server_zanghao.jpg", file2)//两个addFile就是多文件上传,注释掉一个就是单文件上传
                .url(url)

// .params(params)//

                .build()//
                .execute(new MyStringCallBack());//回调
    }

回调处理

/**

 * 用于回调
 * @author Mloong
 *
 */
private class MyStringCallBack extends StringCallback{
    
    @Override
    public void onBefore(Request request, int id) {
        // TODO Auto-generated method stub
        super.onBefore(request, id);
        
        setTitle("loading...");
    }
    
    @Override
    public void onAfter(int id) {
        // TODO Auto-generated method stub
        super.onAfter(id);
        
        setTitle("sample-okhttp");
    }

    //出错
    @Override
    public void onError(Call arg0, Exception e, int arg2) {
    
        e.printStackTrace();
        
        tv_result.setText("onError:"+e.getMessage());
        
        
        
    }

    //成功后回调
    @Override
    public void onResponse(String response, int id) {
        
        //显示文本信息
        tv_result.setText("onResponse:"+ response);
        
        switch (id) {
        case 100:
            
            Toast.makeText(OKHttpActivity.this, "http", Toast.LENGTH_LONG).show();
            
            break;
            
        case 101:
            
            Toast.makeText(OKHttpActivity.this, "https", Toast.LENGTH_LONG).show();
            
            break;

        default:
            break;
        }
        
    }
    
    @Override
    public void inProgress(float progress, long total, int id) {
        
        Log.e(TAG, "inProgress:"+progress);
        
        mProgressBar.setProgress((int) (100*progress));

    }
    
}

四、项目源码下载
链接:https://pan.baidu.com/s/1f3eZhmfKakrd9zaGzX8_gQ
密码:cv4b

原文地址https://www.cnblogs.com/WUXIAOCHANG/p/10646545.html

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android学习:OkHttp进行网络请求等
OkHttp是一个优秀的网络请求框架,主要介绍介绍OkHttp的Get请求、Post请求、上传下载文件、 上传下载图片等功能。
0 0
Android开发之OkHttp介绍
Android开发之OkHttp介绍
0 0
Android OkHttp+Retrofit+RxJava搭建网络访问框架(含源码)
Android OkHttp+Retrofit+RxJava搭建网络访问框架(含源码)
0 0
Android | 网络技术基础梳理——WebView以及HTTP运用(HttpURLConnection及OkHttp)、XML以及JSON解析(demo+bug)
Android | 网络技术基础梳理——WebView以及HTTP运用(HttpURLConnection及OkHttp)、XML以及JSON解析(demo+bug)
0 0
【Android】网络编程之OKHTTP与Retrofit框架
上一期我们实现了Android的网络编程,通过Java代码在子线程中请求数据,再通过Java代码解析json数据,因为对于较复杂的json数据,通过java代码需要逐层解析比较困难,所以我们又通过第三方框架GSON,使用它可以直接将字符串解析成对象,并且封装成为一个实体类,配合实体类插件GsonFormatPlus,让我们只需通过简单的几行代码就实现数据解析
0 0
android源码宇宙——Okhttp
android源码宇宙——Okhttp
0 0
Android OkHttp使用和源码详解(下)
对于 Request 的 Head 以及 TCP 链接,我们能控制修改的成分不是很多。所以咱们了解 CacheInterceptor 和 CallServerInterceptor。
0 0
Android OkHttp使用和源码详解(上)
OkHttp 是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用。对于 Android App 来说,OkHttp 现在几乎已经占据了所有的网络请求操作,RetroFit + OkHttp 实现网络请求似乎成了一种标配。因此它也是每一个 Android 开发工程师的必备技能,了解其内部实现原理可以更好地进行功能扩展、封装以及优化。
0 0
温故而知新!做了3年Android还没看过OkHttp源码?灵魂拷问
温故而知新!做了3年Android还没看过OkHttp源码?灵魂拷问
0 0
【OkHttp】Android 项目导入 OkHttp ( 配置依赖 | 配置 networkSecurityConfig | 配置 ViewBinding | 代码示例 )(二)
【OkHttp】Android 项目导入 OkHttp ( 配置依赖 | 配置 networkSecurityConfig | 配置 ViewBinding | 代码示例 )(二)
0 0
+关注
优惠码发放
阿里云优惠码阿里云推荐券bieryun.com
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Android组件化实现
立即下载
蚂蚁聚宝Android秒级编译—— Freeline
立即下载
Android插件化:从入门到放弃
立即下载