zoukankan      html  css  js  c++  java
  • okHttp使用

    本文转载自:http://www.cnblogs.com/qifengshi/p/5405550.html

    okHttp是一个http请求框架,相当于android原生的httpclient和httpURLConnectiond的封装,让写法更加简单,可以处理更加复杂的网络请求;

    OkHttp使用

      Gradle导入:

     compile 'com.squareup.okhttp3:okhttp:3.2.0'
     compile 'com.squareup.okio:okio:1.6.0'
    

     或者用meven导入;

     使用get请求:get分为get同步请求和get异步请求:

     首先定义一个okhttpclient和Requeset:

    private OkHttpClient client = new OkHttpClient();
    
    Request request = new Request.Builder().
    url("http://www.baidu.com").
    build();
    

      也可以在创建Requeset的时候就传入参数:

    Request request = new Request.Builder().
                   url("http://www.baidu.com").
                   addHeader("User-Agent","android").
                  header("Content-Type","text/html; charset=utf-8").
                  build();
    

     

    通过addHeader和header方法为请求增加请求头部,注意使用header(name, value)可以设置唯一的name、value。如果已经有值,旧的将被移除,然后添加新的。使用addHeader(name, value)可以添加多值(添加,不移除已有的)。

    同步的get方法,通过client.newCall(request).execute()方法得到请求的response.

    Response response = okHttpClient.newCall(request).execute();

    OkHttp封装了很多处理response的方法,比如response.headers()的得到headers

    Headers headers = response.headers();
     for (int i = 0; i < headers.size(); i++) {
    System.out.println(headers.name(i) + ": " + headers.value(i)); }
    

    就得到请求头的内容:

    Date: Mon, 18 Apr 2016 05:23:43 GMT
    Content-Type: text/html; charset=utf-8
    Transfer-Encoding: chunked
    Connection: Keep-Alive
    Vary: Accept-Encoding
    Set-Cookie: BAIDUID=A323EC9BF678C0EB78E20741FD71211B:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
    Set-Cookie: BIDUPSID=A323EC9BF678C0EB78E20741FD71211B; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
    Set-Cookie: PSTM=1460957023; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
    Set-Cookie: BDSVRTM=0; path=/
    Set-Cookie: BD_HOME=0; path=/
    Set-Cookie: H_PS_PSSID=1434_19672_18281_19690_17948_18205_19558_15952_12257; path=/; domain=.baidu.com
    P3P: CP=" OTI DSP COR IVA OUR IND COM "
    Cache-Control: private
    Cxy_all: baidu+2db7793e0e32b9f6c20be8f623e1ae43
    Expires: Mon, 18 Apr 2016 05:22:55 GMT
    X-Powered-By: HPHP
    Server: BWS/1.1
    X-UA-Compatible: IE=Edge,chrome=1
    BDPAGETYPE: 1
    BDQID: 0xfacc6fc10004ca96
    BDUSERID: 0
    OkHttp-Sent-Millis: 1460957021226
    OkHttp-Received-Millis: 1460957021430

    响应报文的实体可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。

    异步的get请求得到的response方法是通过如下方法:

    okHttpClient.newCall(request).enqueue(new Callback() {
                            @Override
                            public void onFailure(Call call, IOException e) {
                            }       
                            @Override
                            public void onResponse(Call call, Response response) throws IOException {
                            }
                  });
    

      在onResponse方法中,执行请求成功的代码,onFailure方法中,执行请求失败的代码

      下面给一个完整的异步get的栗子

    import android.os.Bundle;
    import android.os.Handler;
    import android.support.v7.app.AppCompatActivity;
    import android.text.method.ScrollingMovementMethod;
    import android.widget.TextView;
    
    import java.io.IOException;
    
    import okhttp3.Call;
    import okhttp3.Callback;
    import okhttp3.Headers;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.Response;
    
    public class MainActivity extends AppCompatActivity {
    
        private OkHttpClient okHttpClient = new OkHttpClient();
        public TextView show;
        public Handler handler = new Handler();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            show = (TextView) findViewById(R.id.show);
            show.setMovementMethod(ScrollingMovementMethod.getInstance());
            Request request = new Request.Builder().
                    url("http://www.baidu.com").
                    addHeader("User-Agent", "android").
                    header("Content-Type", "text/html; charset=utf-8").
                    get().
                    build();
            okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
    
                }
                @Override
                public void onResponse(Call call, final Response response) throws IOException {
                    final Headers headers = response.headers();
                    final String str = response.body().string();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < headers.size(); i++) {
                                show.append(headers.name(i) + ": " + headers.value(i));
                                show.append(str);
                            }
                        }
                    });
    
                }
            });
    
    
        }
    
    }
    

      其实按照官网说的,回调是发生在response 的headers准备好就发生的,所以有时候请求response的实体部分会发生阻塞。

    post请求——键值对为参数。

    post请求和get请求除了在构建request上面不同以外,在处理response上面都是一样的,所以下面我们只讨论一下post构建request,当然post也是支持同步post和异步post的,可以参考get方法。
    在构建post的request时候,首先用FormBody.Builder去构建request的body部分,栗子如下,当然这是OKHttp3的方法.

    FormBody.Builder builder = new FormBody.Builder();
            for(int i = 0 ; i < key.size() ;i ++){
                builder.add(key.get(i),value.get(i));
            }
            RequestBody body = builder.build();
    

      

    builder中add的是要加入的参数键值对。得到要构造的body后用

    Request request = new Request.Builder().url(url).post(body).build();

    获得请求的request,后面的操作就和get方法是一样的,这里可以参考异步get的栗子,构建一个post的request.下面的写法原封不变。

    post请求--多种类型的body

    上文已经说了post和get的用法主要在构建不同的request上面,所以接下来我们主要讨论的也是如何构建request.
    参考上面,我们首先要创建一个requestBody,我们可以用下面的方式去构建,当然这也是okhttp3的方法

    MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

    已表单上传的形式去提交post。我们看一下builder的方法

     /** Add a part to the body. */
        public Builder addPart(RequestBody body) {
          return addPart(Part.create(body));
        }
    
        /** Add a part to the body. */
        public Builder addPart(Headers headers, RequestBody body) {
          return addPart(Part.create(headers, body));
        }
    
        /** Add a form data part to the body. */
        public Builder addFormDataPart(String name, String value) {
          return addPart(Part.createFormData(name, value));
        }
    
        /** Add a form data part to the body. */
        public Builder addFormDataPart(String name, String filename, RequestBody body) {
          return addPart(Part.createFormData(name, filename, body));
        }
    

      

    从这里我们可以看出可以直接用 public Builder addFormDataPart(String name, String filename, RequestBody body)上传一个File,最后一个参数是请求的实体,可以通过 RequestBody.create(final MediaType contentType, final File file) 获得,而MediaType则可以通过下面方法获得

    //调用judgeType方法
    private static final MediaType MEDIA_TYPE = MediaType.parse(judgeType(fileName);
    //judge方法如下
    private String judgeType(String path) {
            FileNameMap fileNameMap = URLConnection.getFileNameMap();
            String contentTypeFor = fileNameMap.getContentTypeFor(path);
            if (contentTypeFor == null) {
                contentTypeFor = "application/octet-stream";
            }
            return contentTypeFor;
        }
    

      

    由于我后台能力比较渣,这里用一个官网的例子来实现一遍我刚才讨论的方法。

    MultipartBody.Builder builder = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("image", "logo-square.png",
                RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")));
    RequestBody requestBody = builder.build();
     
     Request request = new Request.Builder()
           .header("Authorization", "Client-ID " +"9199fdef135c122")
            .url("https://api.imgur.com/3/image")
            .post(requestBody)
            .build();
    

      

    当然除了这个方法以外,调用如下方法也是可以的,我们可以利用name和filename自己构造Header传上去。

    public Builder addPart(Headers headers, RequestBody body) {
          return addPart(Part.create(headers, body))
    

      

    栗子如下:

    builder.addPart(Headers.of("Content-Disposition", "form-data; name="" + name + ""; filename="" + fileName + """),fileBody);
    

      

    后面的写法和上面类似,这样我们就实现了文件上传的写法。

    文件下载

    刚才我们上面已经说了,希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。换句话说,文件的下载可以简单的通过get请求,得到相应的response,在把他的实体转换成二进制流写入文件,就是实现了文件的下载。主要的写法就是文件的读写,跟OKHttp关系不大,当然我们也可以用okio来实现文件的读写,这里水平有限就不介绍了。下面给一个简单的例子。

    private void _download(final String url, final String destFileDir, final ResultCallback callback) {
            final Request request = new Request.Builder().url(url).build();
            final Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
    
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    InputStream is = null;
                    byte[] buf = new byte[2048];
                    int len = 0;
                    FileOutputStream fos = null;
                    try {
                        is = response.body().byteStream();
                        File file = new File(destFileDir, getFileName(url));
                        fos = new FileOutputStream(file);
                        while((len = is.read(buf)) != -1){
                            fos.write(buf,0,len);
                        }
                        fos.flush();
                       //....省略后续对已经保存的文件的操作
                       
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        try {
                            if (is != null) is.close();
                        } catch (IOException e) {
    
                        }
                        try
                        {
                            if (fos != null) fos.close();
                        } catch (IOException e)
                        {
                        }
                    }
                }
            });
        }
    

      

      

     

     
     
     

      

     

      

  • 相关阅读:
    泡泡H5这封企业剪彩活动邀请函好像挺专业!
    教你 Shiro + SpringBoot 整合 JWT
    Thymeleaf 获取后端Model中的数据
    SpringBoot 之 普通类获取Spring容器中的bean ,
    如何用JS判断网页中某个id的网页元素是否存在(两种写法 jQuery写法和原始写法:
    前台请求不带cookie的问题解决方案大汇总
    js访问函数内部的变量(三种方法)
    源码分析:若依用户 user_id查询返回除了用户表,为何还带有部门dept和角色role表呢
    关于若依前端分页首次使用BootstrapPager 即bootstrap扩展插件
    关于若依需要验证码,PostMan是如何登陆流程
  • 原文地址:https://www.cnblogs.com/yjpjy/p/5415778.html
Copyright © 2011-2022 走看看