开源框架OKHttp的使用01-基础

来源:互联网 发布:阿里云服务器能翻墙么 编辑:程序博客网 时间:2024/06/01 09:25

一、简介

Android系统提供了两种HTTP通信类,HttpURLConnection和HttpClient
尽管Google在大部分安卓版本中推荐使用HttpURLConnection,但是这个类相比HttpClient实在是太难用,太弱爆了。OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。使用时要求jdk及1.7以上。
下载:https://github.com/square/okhttp
okhttp内部依赖okio,需要同时导入okio
https://search.maven.org/remote_content?g=com.squareup.okio&a=okio&v=LATEST

也可以使用构建的方式进行导入,会自动从框架库中下载
MAVEN:

<dependency>  <groupId>com.squareup.okhttp</groupId>  <artifactId>okhttp</artifactId>  <version>2.4.0</version></dependency>

GRADLE

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

二、使用场景

一般的get请求
一般的post请求
基于Http的文件上传
文件下载
加载图片
支持请求回调,直接返回对象、对象集合
支持session的保持

三、使用示例

okhttp网络请求分为同步请求和异步请求。
异步请求执行方法:

Call call = client.newCall(request);call.enqueue(new Callback(){...});

异步请求数据示例

private void okhttpA(String url) {        // 1.需要一个OkHttpClient对象,最好一个app中只实例化一个该对象。        OkHttpClient client = new OkHttpClient();        // 2.新建一个请求        Request request = new Request.Builder().url(url).build();        // 3.执行请求,获得响应的结果        Call call = client.newCall(request);        // 4.加入调度        final TextView tv = new TextView(this);        call.enqueue(new Callback() {            @Override            public void onResponse(Response response) throws IOException {                if (response.isSuccessful()) {                    final String str = response.body().string();                    runOnUiThread( new Runnable() {                        public void run() {                            tv.setText(str);                        }                    });                } else {                    throw new IOException("Unexpected code " + response);                }            }            @Override            public void onFailure(Request arg0, IOException arg1) {            }        });    }

同步请求执行方法:

Call call = client.newCall(request);call.execute();

同步请求数据示例

private String okhttpB(String url) throws IOException {        OkHttpClient client = new OkHttpClient();        Request request = new Request.Builder().url(url).build();        Call call = client.newCall(request);        Response response = call.execute();        if (response.isSuccessful()) {            return response.body().string();        } else {            throw new IOException("Unexpected code " + response);        }    }

下面主要示例都以异步为主:
1.一般的get请求

    private void okhttpGet(String url){        //1.需要一个OkHttpClient对象,最好一个app中只实例化一个该对象。        OkHttpClient client = new OkHttpClient();        //2.新建一个请求        Request request = new Request.Builder().url(url).build();        //3.执行请求,获得响应的结果        Call call = client.newCall(request);        //4.加入调度        call.enqueue(new Callback() {            @Override            public void onResponse(Response arg0) throws IOException {                // TODO Auto-generated method stub            }            @Override            public void onFailure(Request arg0, IOException arg1) {                // TODO Auto-generated method stub            }        });    }

2.post提交,提交各种类型数据
这种提交形式和服务器有关,有些服务器不支持这种数据处理。

①提交json类型字符串

public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");private void okhttpPostWithJson(String url)  {        String json ="";    //一个Json字符串        // 1.创建OkHttpClient        OkHttpClient client = new OkHttpClient();        // 2.新建请求体,放入参数        RequestBody body = RequestBody.create(JSON, json);        // 3.新建请求        Request request = new Request.Builder().url(url).post(body).build();        // 4.new call        Call call = client.newCall(request);        //5.监听回调        call.enqueue(new Callback() {            @Override            public void onResponse(Response arg0) throws IOException {                // TODO Auto-generated method stub            }            @Override            public void onFailure(Request arg0, IOException arg1) {                // TODO Auto-generated method stub            }        });    }

②这个例子提交了一个markdown文档到web服务,以HTML方式渲染markdown。因为整个请求体都在内存中,因此避免使用此api提交大文档(大于1MB)。

    public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");    private final OkHttpClient client = new OkHttpClient();    public void run() throws Exception {        String postBody = ""            + "Releases\n"            + "--------\n"            + "\n"            + " * _1.0_ May 6, 2013\n"            + " * _1.1_ June 15, 2013\n"            + " * _1.2_ August 11, 2013\n";        Request request = new Request.Builder()            .url("https://api.github.com/markdown/raw")            .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))            .build();        Response response = client.newCall(request).execute();        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);        System.out.println(response.body().string());    }

③使用流的方式,POST提交请求体。请求体的内容(也就是携带的数据体)由流写入产生。这个例子是流直接写入Okio的BufferedSink。你的程序可能会使用OutputStream,你可以使用BufferedSink.outputStream()来获取一个OutputStream实例。

public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");    private final OkHttpClient client = new OkHttpClient();    public void okhttpPostStream() throws Exception {        //1.携带的数据体        RequestBody requestBody = new RequestBody() {            //文件类型            @Override            public MediaType contentType() {                return MEDIA_TYPE_MARKDOWN;            }            //写入的数据内容            @Override            public void writeTo(BufferedSink sink) throws IOException {                sink.writeUtf8("Numbers\n");                sink.writeUtf8("-------\n");                for (int i = 2; i <= 997; i++) {                    sink.writeUtf8(String.format(" * %s = %s\n", i, factor(i)));                }            }            private String factor(int n) {                for (int i = 2; i < n; i++) {                    int x = n / i;                    if (x * i == n)                        return factor(x) + " × " + i;                }                return Integer.toString(n);            }        };        //2.请求体        Request request = new Request.Builder()                .url("https://api.github.com/markdown/raw")                .post(requestBody)                .build();        //3.执行请求,获得返回结果        Response response = client.newCall(request).execute();        if (!response.isSuccessful())            throw new IOException("Unexpected code " + response);        System.out.println(response.body().string());    }

④上传一个本地文件

public static final MediaType MEDIA_TYPE_MARKDOWN= MediaType.parse("text/x-markdown; charset=utf-8");    private final OkHttpClient client = new OkHttpClient();    public void okhttpPostFile() throws Exception {        File file = null;        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {            //sd卡不存在            return;        }        file = new File(Environment.getExternalStorageDirectory()+"/readme.txt");        if(!file.exists()){            //文件不存在            return;        }        Request request = new Request.Builder()            .url("https://api.github.com/markdown/raw")            .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))            .build();        Response response = client.newCall(request).execute();        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);        System.out.println(response.body().string());    }

3.post提交,参数为键值对

private void okhttpPostWithParams(String url) throws IOException {        OkHttpClient client = new OkHttpClient();        RequestBody body = new FormEncodingBuilder()                .add("id", "154")                .add("name", "Jack")                .add("password", "123456")                .build();        Request request = new Request.Builder()            .url(url)            .post(body)            .build();        Call call = client.newCall(request);        call.enqueue(new Callback() {            @Override            public void onResponse(Response arg0) throws IOException {                // TODO Auto-generated method stub            }            @Override            public void onFailure(Request arg0, IOException arg1) {                // TODO Auto-generated method stub            }        });    }

4.提取响应头信息

private final OkHttpClient client = new OkHttpClient();    public void okhttpGetHeader() throws Exception {        Request request = new Request.Builder()            .url("https://api.github.com/repos/square/okhttp/issues")            .header("User-Agent", "OkHttp Headers.java")            .addHeader("Accept", "application/json; q=0.5")            .addHeader("Accept", "application/vnd.github.v3+json")            .build();        Response response = client.newCall(request).execute();        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);        System.out.println("Server: " + response.header("Server"));        System.out.println("Date: " + response.header("Date"));        System.out.println("Vary: " + response.headers("Vary"));    }

5post提交分块请求
MultipartBuilder可以构建复杂的请求体,与HTML文件上传形式兼容。多块请求体中每块请求都是一个请求体,可以定义自己的请求头。这些请求头可以用来描述这块请求,例如他的Content-Disposition。如果Content-Length和Content-Type可用的话,他们会被自动添加到请求头中。

private static final String IMGUR_CLIENT_ID = "...";    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");    private final OkHttpClient client = new OkHttpClient();    public void okhttpPostMultipart() throws Exception {        // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image        RequestBody requestBody = new MultipartBuilder()            .type(MultipartBuilder.FORM)            .addPart(                Headers.of("Content-Disposition", "form-data; name=\"title\""),                RequestBody.create(null, "Square Logo"))            .addPart(                Headers.of("Content-Disposition", "form-data; name=\"image\""),                RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))            .build();        Request request = new Request.Builder()            .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)            .url("https://api.imgur.com/3/image")            .post(requestBody)            .build();        Response response = client.newCall(request).execute();        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);        System.out.println(response.body().string());    }

6.使用Gson来解析JSON响应
Gson是一个在JSON和Java对象之间转换非常方便的api。这里我们用Gson来解析JSON响应。
注意:ResponseBody.charStream()使用响应头Content-Type指定的字符集来解析响应体。默认是UTF-8。

private final OkHttpClient client = new OkHttpClient();    private final Gson gson = new Gson();    public void run() throws Exception {        Request request = new Request.Builder()            .url("https://api.github.com/gists/c2a7c39532239ff261be")            .build();        Response response = client.newCall(request).execute();        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);        Gist gist = gson.fromJson(response.body().charStream(), Gist.class);        Set<Entry<String, GistFile>> entrySet =  gist.files.entrySet();        for(Entry<String, GistFile> entry:entrySet){             System.out.println(entry.getKey());             System.out.println(entry.getValue().content);        }    }    static class Gist {        Map<String, GistFile> files;    }    static class GistFile {        String content;    }

7.图片下载

     byte[] data = response.body().bytes();     Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);

8.文件下载

     InputStream is = response.body().byteStream();     byte[] buffer = new byte[1024];     File file = new File(Environment.getExternalStorageDirectory(), "aa.mp3");     FileOutputStream fos = new FileOutputStream(file);     while( (is.read(buffer)) != -1 ){        fos.write(buffer, 0, buffer.length);        fos.flush();     }     is.close();     fos.close();

9.其他
①取消一个call

 call.cancel();

②设置超时时间

    client = new OkHttpClient();    client.setConnectTimeout(10, TimeUnit.SECONDS);    client.setWriteTimeout(10, TimeUnit.SECONDS);    client.setReadTimeout(30, TimeUnit.SECONDS);

③克隆一个client,基本配置和原来的一样,但是我们可以在克隆之后的client进行修改。

    private final OkHttpClient client = new OkHttpClient();    public void okhttpClone(){        Request request = new Request.Builder()            .url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay.            .build();        //克隆OkHttpClient        try {            OkHttpClient client1 = client.clone();            client1.setReadTimeout(500, TimeUnit.MICROSECONDS);            Call call1 = client1.newCall(request);            Response response1;            response1 = call1.execute();            System.out.println("Response 1 succeeded: " + response1);        } catch (IOException e) {            e.printStackTrace();            System.out.println("Response 1 failed: " + e);        }        try {            OkHttpClient client2 = client.clone();            client2.setReadTimeout(3000, TimeUnit.MICROSECONDS);            Call call2 = client2.newCall(request);            Response response2;            response2 = call2.execute();            System.out.println("Response 2 succeeded: " + response2);        } catch (IOException e) {            e.printStackTrace();            System.out.println("Response 2 failed: " + e);        }    }

参考文章:http://www.cnblogs.com/ct2011/p/3997368.html

0 0