OKhttp使用入门篇

OKhttp使用入门篇

Okhttp是当下非常流行的网络框架,是相对比较成熟的解决方案,本文主要作为学习笔记之用:

支持HTTP2/SPDY黑科技
socket自动选择最好路线,并支持自动重连
拥有自动维护的socket连接池,减少握手次数
拥有队列线程池,轻松写并发
拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING)
基于Headers的缓存策略


1.同步GET

访问网络必须在子线程进行,更新UI需要在主线程

new Thread(new Runnable() {
  @Override
    public void run() {
    try {
    //构建方式有2种,任选其一就行
    OkHttpClient client = new OkHttpClient();//方式1
//  OkHttpClient client1=new OkHttpClient.Builder().build();//方式2
    Request request = new Request.Builder().url(                                   "你的url").get().build();//创建请求
    //通过请求获取回调
    Call call = client.newCall(request);
    //执行请求
    Response response = call.execute();
//   byte[] bytes = response.body().bytes();//通过获取字节数组方式获取内容
//   final String str = new String(bytes, "utf-8");
     final String str=response.body().string();//获取字符串方式
     //主线程更新UI
     runOnUiThread(new Runnable() {
     @Override
     public void run() {
     “这里使用你获取的str进行一些UI操作”
     }
   });
     } catch (IOException e) {
       e.printStackTrace();
         }
                    }
                }).start();//记得开启线程
            }
        });

2异步GET

其他没什么区别,就是多了一句话 client.newCall(request).enqueue(new Callback() )而已,会自动重写两个方法。只需要填入你后续需要进行的操作就可以了,okhttp会帮我们开线程,所以,onFailure跟onResponse都是在子线程里

                        try {

                            OkHttpClient client = new OkHttpClient();//方式1
//                    OkHttpClient client1=new OkHttpClient.Builder().build();//方式2
                            Request request = new Request.Builder().url("http://192.168.56" +
                                    ".1:10086/oschina/list/tweet_list/page0.xml").get().build();
                            //创建请求
                            client.newCall(request).enqueue(new Callback() {
                                @Override
                                public void onFailure(Call call, IOException e) {



                                }

                                @Override
                                public void onResponse(Call call, Response response) throws IOException {
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            textView.setText("233");
                                        }
                                    });
                                }
                            });

                        } catch (Exception e) {
                            e.printStackTrace();
                        }

3文件上传(post请求)

这一步跟异步请求唯一不同的一点就是设置了请求体的内容,就是那么两段话
RequestBody fileBody=RequestBody.create(MediaType.parse(“application/octet-stream”), file);
创建混合请求体,可以同时传多个数据
RequestBody body=new MultipartBody.Builder()
通过post(body)上传,具体代码如下:

File file=new File(getCacheDir().getPath(),"/icon_my_message.png");
                        RequestBody fileBody=RequestBody.create(MediaType.parse
                                ("application/octet-stream"), file);//使用MediaType来进行来转换文件内容到请求体中
                        RequestBody body=new MultipartBody.Builder()//设置请求体
              .setType(MultipartBody.FORM)//设置
               .addFormDataPart("name", "Tom")//设置用户名,这个根据你服务器来定
               .addFormDataPart("hehe", "xixi.jpg", fileBody)//设置你要传送的文件,中间是你自己定义的文件名
               .build();//开始构建
                        OkHttpClient client=new OkHttpClient.Builder().build();
                        Request request=new Request.Builder()
                                .url("http://192.168.56.1:10086/android-corebase-day11/upload")
                                .post(body)
                                .build();
                        client.newCall(request).enqueue(new Callback() {
                            @Override
                            public void onFailure(Call call, IOException e) {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                       “若需要更新UI,在这里进行”
                                    }
                                });
                            }

                            @Override
                            public void onResponse(Call call, Response response) throws IOException {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                         “若需要更新UI,在这里进行”
                                    }
                                });
                            }
                        });

4.文件下载

这个异常简单,就不细说了,操作下载的文件可根据需要转换为自己所要的格式进行操作,在回调里,如果需要改变UI,记得扔到主线程操作,回调里面重写的方法都是在子线程里,切记。

    final OkHttpClient client=new OkHttpClient.Builder().build();
                final Request request=new Request.Builder()
                                .url("http://192.168.56.1:10086/oschina/list/tweet_list/page0.xml")
                                .get()
                                .build();
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Log.e("itcast","失败了");
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        File file=new File(filepath+"/aaa.xml");
                        FileOutputStream fos=new FileOutputStream(file);
                        InputStream is=response.body().byteStream();
                        byte[] bt=new byte[1024];
                        int len=0;
                        while((len=is.read(bt))!=-1) {
                            fos.write(bt, 0, len);
                        }
                        fos.close();

                    }
                });

5.文件上传,带进度条的

这里我用了系统自带的进度条对话框,并且已经封装成一个工具类

//首先创建一个进度条
                final ProgressDialog progressDialog=new ProgressDialog(context);
                progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                progressDialog.setCancelable(false);
                progressDialog.show();
                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        UpLoadUtil.postFileWithProgress(context,url,filepath,filename,progressDialog);//调用者一个方法就可以了,5个参数分别的意义是context上下文对象,url你需要的访问的链接,filepath你要上传的文件路径,filename你上传的文件名,progressDialog你设置的进度条对话框,根据需要可改成其他样式

                    }
                }).start();

下面是完整的上传实现类。注释写了挺久。

public class UpLoadUtil {


    interface ProgressRequestListener{
        //定义接口监听文件上传进度,参数意义:1已读数据,2全部数据,3是否结束
        void onRequestProgress(long bytesWritten, long contentLength, boolean done);
    }

    static class ProgressRequestBody extends RequestBody {
        //自定义请求体,继承请求体
        private final RequestBody requestBody;//请求体
        private final ProgressRequestListener progressListener;//回调自定义接口
        private BufferedSink bufferedSink;//包装完成的bufferedsink(缓存池)
        //提供上传进度构造方法
        public ProgressRequestBody(RequestBody requestBody,
                                   ProgressRequestListener progressListener) {
            this.requestBody = requestBody;
            this.progressListener = progressListener;
        }


        //返回MediaType,传入的requestBody中获取,(如"application/octet-stream")
        @Override
        public MediaType contentType() {
            return requestBody.contentType();
        }

        //重写全部长度方法,从请求体中获取文件总长
        @Override
        public long contentLength() throws IOException {
            long length=requestBody.contentLength();
            return length;
        }

        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            if (bufferedSink==null){
                //包装,调用自定义的sink方法
                bufferedSink= Okio.buffer(sink(sink));
            }
            //将缓存写入到请求体重
            requestBody.writeTo(bufferedSink);
            //释放缓存。避免最后一部分数据可能不会被写入
            bufferedSink.flush();
        }

        private Sink sink(Sink sink){
            //正在上传的文件
            return new ForwardingSink(sink) {
                //当前写入字节数
                long bytesWritten=0L;
                //总字节长度,避免多次调用contentLength()方法
                long contentLength=0L;

                @Override
                public void write(Buffer source, long byteCount) throws IOException {
                    super.write(source, byteCount);
                    if (contentLength==0){
                        //获得contentLength的值,后续不再调用
                        contentLength=contentLength();
                    }
                    //增加当前写入的字节数
                    bytesWritten+=byteCount;

                    progressListener.onRequestProgress(bytesWritten,contentLength,
                            bytesWritten==contentLength);
                }
            };
        }
    }

    public static void postFileWithProgress(final Context context, String url, String filePath,
                                            String fileName, final ProgressDialog progressDialog){
        //url就是上传到服务器地址,upload会处理上传的请求体,需要部署并开启servlet
//        String url= "http://192.168.56.1:10086/android-corebase-day11/upload";

        ProgressRequestListener requestListener=new ProgressRequestListener() {
            //            重写接口方法,打印进度
            @Override
            public void onRequestProgress(final long bytesWritten, final long contentLength, boolean done) {
//                Log.e("--contentLength--", "----" + contentLength);
//                Log.e("--bytesRead--", "----" + bytesWritten);
                Log.e("--进度--",bytesWritten*100/contentLength+"%");
                ((Activity)context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (contentLength==bytesWritten){
                            progressDialog.dismiss();
                            Toast.makeText(context,"上传成功",Toast.LENGTH_LONG).show();
                        }else {
                            progressDialog.setMax((int) contentLength);
                            progressDialog.setProgress((int) bytesWritten);
                        }
                    }
                });

            }
        };
        //给出文件地址context.getCacheDir().getPath(),"/icon_my_message.png"
        File file=new File(filePath+"/"+fileName);
        //创建客户端
        OkHttpClient client=new OkHttpClient.Builder().build();
        //创建混合请求体。上传者addFormDataPart("name","tom")这里是上传者是tom根据filename
        //后缀判断,xixi.jpg后缀是jpg,服务端会以流的形式写入到服务端指定的文件夹中
        //以流的形式将文件读取到fileBody中
        RequestBody fileBody=RequestBody.create(MediaType.parse("application/octet-stream"),file);
        RequestBody body=new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("name","tom")
                .addFormDataPart("hehe",fileName,fileBody)//"xixi.jpg"
                .build();
        //创建ProgressRequestBody对象,带进度的请求体
        RequestBody bodyWithProgress=new ProgressRequestBody(body,requestListener);

        // 创建请求
        Request request=new Request.Builder()
                .url(url)//请求地址
                .post(bodyWithProgress)//请求体
                .build();

        // 执行请求
        client.newCall(request).enqueue(new Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.e("MainActivity", response.body().string());
                ((Activity)context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.e("itcast","成功");
                    }
                });
            }

            @Override
            public void onFailure(Call call, IOException e) {
                ((Activity)context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.e("itcast","失败");
                    }
                });
            }

        });

    }
}

总结:Okhttp简单易用,还有个带进度条的文件下载,这个就不细说了,上传的时候,还需要开启服务器的servlet进行操作,不然是传不上去的。。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值