您的位置:首页 > 理论基础 > 计算机网络

OKhttp使用入门篇

2016-04-07 12:11 435 查看

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进行操作,不然是传不上去的。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: