简介:一个处理网络请求的开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献,用于替代HttpUrlConnection和Apache HttpClient。OkHttp可以支持安卓2.3及以上版本,需要jdk1.7及以上;OkHttp有2.x和OkHttp3.x版本之间的部分方法的使用有一点的差异。

优点(百度百科):
1、允许连接到同一个主机地址的所有请求,提高请求效率
2、共享Socket,减少对服务器的请求次数
3、通过连接池,减少了请求延迟
4、缓存响应数据来减少重复的网络请求
5、减少了对数据流量的消耗
6、自动处理GZip压缩

对于OkHttp在使用前,需要在工程中引入OkHttp包,OkHttp还依赖另一个okio包,同样需要引入。也可以在相应的model中的build.gradle配置文件中填入,然后将工程同步一下,环境会自动去下载需要的包:

compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okio:okio:1.7.0'
//可以修改版本号
<user-permission andriod:name="andriod.premission.INTERNET"/>  <!--用户连接网络权限-->


OkHttp的初次学习需要掌握的基本类有:OkHttpClient、RequestBody、Request、Call和Response... ...


1、OkHttpClient:
        对于该类创建对象实例化的方式有两种:标准默认型还有自定义的形式 

//标准形式:
    OkHttpClient mOkHttpClient = new OkHttpClient();
//自定义形式:
    OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
               .connectTimeout(10,TimeUtil.SECONDS)    //为新连接设置默认连接超时时长,第一个参数时大小,第二个参数是单位
               .readTimeout(10,TimeUtil.SECONDS)       //设置新连接的默认读取超时时长
               .writeTimeout(10,TimeUtil.SECONDS)      //设置新连接的默认写入超时时长
               .cache(setCache)    //设置用于读取和写入缓存响应的响应缓存  [1]
               .build();

[1]:参数为Cache对象     File filePath = new File(getExternalCacheDir(),"netCache");     int cacheSize = 10 * 1024 * 1024;     Cache setCache = new Cache(filePath,cacheSize); 注:在OkHttp2.+的版本中设置以上的超时的方法与3.+版本不同:        mOkHttpClient.setConnectTimeout(10,TimeUtil.SECONDS);     mOkHttpCLient.setConnectTimeout(10,TimeUtil.SECONDS);     mOkHttpClient.setConnectTimeout(10,TimeUtil.SECONDS);     mOkHttpClient.setCache(setCache);

2、RequestBody:
        该类对于OkHttp的post方法使用,是请求体类,用于上传数据使用
        核心方法:contentType、contentLength、create、writeTo方法... ...

public abstract MediaType contentType()
public long MediaType contentLength()
public abstract void writeTo(BufferedSink sink)
public static RequestBody create(MediaType contentType,String content) [2]
    //[2]:第二个参数可以是多种类型;该类存在create的多个重载方法,api点这

        //该类的对象实例化方式:
MediaType mMediaType = MediaType.parse("application/octet-stream");    //
File putFile = new File(Environment.getExternaStorageDirectory(),"文件名.扩展名");   //父路径和子路径两个参数拼接起来为文件地址绝对地址
RequestBody mRequestBody = RequestBody.create(mMediaType,putFile);  [3]
//[3]:第一、第二参数类型均为多种,使用create方法一般用于上传文件或字符串类型数据,对于上传键值对类型数据将会使用另一种方法(另一方式FormBody)
RequestBody mRequestBody = FormBody.Builder()
                .add("key","value1")
                .add("key","value2")
                .build();

3、Request:
        该类用于生成网络连接请求对象,包括多中信息:请求参数,请求头,请求方式...
        常用方法有:url、post、method、headers等方法

Request mRequest = new Request.Builder()
            .url("http://www.baidu.com")
            .post(mRequestBody)  [4]
            .build();
/*[4]:如果不显示调用post方法,该此网络请求将使用get方式请求网络,其中的参数是请求体对象的示例,使用post方式上传数据比get方式更安全,数据大小不受
限制,可以传递更多的参数(对于长表单数据,上传文件很好用)*/

4、Call:
        该类是网络请求执行的最后一个需要实例的对象,该类提供了网络请求的同步与异步连接方式,所有的连接都不在UI线程中,如果在网络请求后,需要更新UI布局就需要调用Handler,有方法:runOnUiThread()方法

Call mCall = mOkHttpClient.newCall(mRequest);
//使用异步网络连接
mCall.enqueue(new CallBack(){
    @override
    public void onFailure(Call call,IOException e){
        //网络连接失败
    }
    @override
    public void onResponse(Call call,Response response){
        if(response.isSuccessful()){
            //请求数据成功,返回code为200~300    [5]   
        }else{
            //请求数据失败
        }
    }
});
[5]:response.isSuccessful()源码:
    public boolean isSuccessful(){
        return code >= 200 && code <= 300;
    }

//使用同步方式需要开启新的子线程,耗时操作不允许在UI主线程中运行
new Thread(new Runnable(){
    Call mCall = mOkHttpClient.newCall(mRequest);
    Response mResponse = mCall.execute();    //涉及到的Response对象知识下一点解说
    if(mResponse.isSuccessful()){
        //网络同步请求成功,更新UI布局需要使用runOnUiThread方法
    }else{

    }
}).start();    //创建一个子线程后需要使用start方法启动该线程

注:runOnUiThread(new Runnable(){
        @override
        public void run(){
            //更新UI的逻辑代码
        }
    });

//同步方法会阻塞当前线程的执行,异步方法不会阻塞当前线程的执行

5、Response:
        该类是网络请求后的响应信息对象,对于服务器返回的数据均存放在该示例对象中,而且对于Response实例一次请求中只能有一次有效调用,如果调用两次将会出现程序错误,因此,这就使得在需要多次使用数据前就要将Response实例中的数据保存下来,Response类提供了多种方法:body、code、protocol、request、isSuccessful、headers(响应头对象)、toString...

Response mResponse = mCall.execute();
if(mResponse.isSuccessful()){
    String str = mResponse.body().string();    [6]
    int code = mResponse.code();
    Protocol protocol = mResponse.protocol();
    Request request = mResponse.request();
    String head = mResponse.toString();    
    Log.i("Response响应信息集:","" + str + code + protocol + request + head);
 }
/*[6]:body为获取的数据没内容,该数据可以为:转化为字符串、字节流、字符流、字节数组等形式数据,有此属性就奠定了OkHttp下载文件的功能,当然可以上传文
件,这是就与第2点联系起来了,第二点中的RequsetBody的实例方法可以将本地文件“放置”到请求体中,这是,服务器端在接收参数时就可以得到用户上传的文件数据*/

这五个点学习后,这时,就可以写出基本的get、post同步或异步的网络连接了。对于OkHttpClient表示HTTP请求的客户端类,大多数情况下推荐只使用创建一个该对象的实例,全局使用


这里贴一个完整的关于post请求的异步方法示例:

public class PostAsyn(){
    private TextView tvShowNetInfo;
    public static OkHttpClient okHttpClient;
    static(
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(15,TimeUnit.SECONDS)
                .readTimeout(15,TimeUnit.SECONDS)
                .writeTimeout(15,TimeUnit.SECOND)
                .build();
    );
    @Overvide
    public void onCreate(Bundle saveInstanceState){
        super.onCreate(saveInstanceState);
        setContentView(R.layout.activity_main);
        tvShowNetInfo = (TextView) findViewId(.tv_show_net_info);
        postAsynDate();
    }
    public void postAsynData(){
        RequestBody requestBody = new FormBody.Builder()
                        .add("key1","value1")
                        .add("key2","value2")
                        .build();
        Request requset = new Request.Builder()
                    .url("http://www.baidu.com")
                    .post(requestBody)
                    .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback(){
                @Overvide
                public void onFailure(Call call,IOException e){
                    goUiThread("网络连接失败");
                }
                @Overvide
                public void onResponse(Call call,Response response){
                    if(response.isSuccessful()){
                        goUiThread("请求数据成功,响应码:" + response.code());
                    }else{
                        goUiThread("网络连接成功,但是没有响应数据,响应码:" + response.code());
                    }
                }
            }
            
        );
    }
    private void goUiThread(final String str){
        runOnUiThread(new Runnable(){
            @Overvide
            public void run(){
                tvShowNetInfo.setText(str);
            }
        });
    }
 }

//对应的布局文件略

//这只是基本的OkHttp操作,其还提供更多的高级使用,例如使用缓存,发送复杂请求体等

参考网址:

http://square.github.io/okhttp/3.x/okhttp/