王学岗OKHttp从简单到复杂
2018-11-02 本文已影响0人
王学岗
第一部分:快速使用
如果你对OkHttp比较熟悉了,完全可以跳过第一部分。
package com.example.okhttptest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private String testUrl = "http://119.253.81.55/tkheal/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void getRequest(View view) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(testUrl + "/rungroup/getRankForGroupUser ").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i("王迪迪",e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i("王迪迪","成功");
//response即是服务端给我们返回的对象
String result = response.body().string();
//因为response是一个流,所以我们需要关闭
if (response.body() != null) {
response.body().close();
}
}
});
}
}
看下打印输出结果
11-01 19:34:23.617 15107-15187/com.example.okhttptest I/王迪迪: 成功
第二部分:Http协议简介
这一部分只是http相关的一些知识,如果你比较熟悉http协议,建议跳过这一部分。
1.png 1.png 1.png 1.png
request介绍
1.png
Response介绍
1.png
第三部分:Get请求
package com.example.okhttptest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private String testUrl = "http://119.253.81.55/tkheal/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void getRequest(View view) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.get()
//拼接请求参数
.url(testUrl + "/rungroup/getRankForGroupUser?groupId=5&type=0&userId=3805&page=1&pageSize=5&token=c9e784425cdc9f7091e5980fd7870b5f")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i("王迪迪",e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i("王迪迪","成功");
//response即是服务端给我们返回的对象
String result = response.body().string();
Log.i("王迪迪","result:"+result);
//因为response是一个流,所以我们需要关闭
if (response.body() != null) {
response.body().close();
}
}
});
}
}
get请求我们可以直接在url地址后面添加参数。使用? &。
第四部分,post请求,使用form表单
首先我推荐一个post测试工具——postman 1.png用户登陆,使用form表单
private void loginWithForm(String name, String password) {
OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
//传入参数
RequestBody body=new FormBody.Builder().add("username",name).add("password",password).build();
final Request request=new Request.Builder()
.url(testUrl)
//声明post请求
.post(body)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
String result=response.body().string();
}
//操作UI
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
});
}
这是用phthon写成的服务端
1.png
第五部分,post请求,使用json数据
这是服务端
1.png
private void loginWithjson(String name, String password) {
OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("username",name);
jsonObject.put("password",password);
} catch (JSONException e) {
e.printStackTrace();
}
String jsonParams=jsonObject.toString();
RequestBody body=RequestBody.create(MediaType.parse("application/json;charset=utf-8"),jsonParams);
final Request request=new Request.Builder()
.url(testUrl2)
//声明post请求
.post(body)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
String result=response.body().string();
}
//操作UI
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
});
}
第六部分,读取okhttp流下载文件
private void downloadFile() {
Request request = new Request.Builder().url(testUrl).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//文件下载要返回的不是一个字符串,而是一个流。我们读取服务器返回的流,然后再写入本地
InputStream is = response.body().byteStream();
File file = null;
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"a.apk");
} else {
file = new File(getCacheDir().getAbsolutePath(), "a.apk");
}
//获取文件的长度
long total=response.body().contentLength();
//当前读取的长度
long sum=0;
FileOutputStream fileOutputStream=new FileOutputStream(file);
byte[] bytes=new byte[1024];
int len=0;
while((len=is.read(bytes))!=-1){
fileOutputStream.write(bytes);
sum=sum+len;
//这里可以使用handler message机制更新进度条,此处我略去,读者自己实现。
int progress = (int) ((float)sum / (float) total);
}
}
//关闭流的操作此处略去
});
}
第七部分,拦截器下载文件
第一步:创建一个类继承ResponseBody
package com.example.okhttptest;
import android.support.annotation.Nullable;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;
public class ProgressResponseBody extends ResponseBody {
private ResponseBody responseBody;
private ProgressListenner progressListenner;
private BufferedSource bufferedSource;
public ProgressResponseBody(ResponseBody responseBody, ProgressListenner progressListenner) {
this.responseBody = responseBody;
this.progressListenner = progressListenner;
}
@Nullable
@Override
public MediaType contentType() {
return responseBody.contentType();
}
@Override
public long contentLength() {
return responseBody.contentLength();
}
@Override
public BufferedSource source() {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(getSourse(responseBody.source()));
}
return bufferedSource;
}
//Okio是OkHttp底层IO操作
//如果我们不实现进度条,那么这里可以什么也不写。
private Source getSourse(Source source) {
return new ForwardingSource(source) {
long totalSize = 0l;
long sum = 0;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long len = super.read(sink, byteCount);
if (totalSize == 0) {
totalSize = contentLength();
}
sum += (len == -1 ? 0 : len);
int progress = (int) ((float) sum / (float) totalSize);
if (len == -1) {
progressListenner.onDone(totalSize);
} else {
progressListenner.onProgress(progress);
}
return len;
}
};
}
public interface ProgressListenner {
void onProgress(int progress);
void onDone(long totalSize);
}
}
package com.example.okhttptest;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private String testUrl = "http://119.253.81.55/tkheal/";
private ProgressBar progressBar;
private OkHttpClient okHttpClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progressbar);
okHttpClient = new OkHttpClient();
initOkHttpClient();
}
public void callNet(View view) {
Request request = new Request.Builder().url(testUrl).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//文件下载要返回的不是一个字符串,而是一个流。我们读取服务器返回的流,然后再写入本地
InputStream is = response.body().byteStream();
File file = null;
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "a.apk");
} else {
file = new File(getCacheDir().getAbsolutePath(), "a.apk");
}
//当前读取的长度
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1) {
fileOutputStream.write(bytes);
}
}
//关闭流的操作此处略去
});
}
private void initOkHttpClient() {
okHttpClient = new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder().body(new ProgressResponseBody(response.body(), new Pg())).build();
}
}).build();
}
private class Pg implements ProgressResponseBody.ProgressListenner {
@Override
public void onProgress(final int progress) {
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setProgress(progress);
}
});
}
@Override
public void onDone(long totalSize) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_LONG).show();
}
});
}
}
}
第六部分:上传文件
private void uploadFele(){
OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
//图片数据类型
// png : image/png
//jpg : image/jpeg
//gif : imge/gif
//其它数据类型
// json : application/json
// xml : application/xml
RequestBody requestBody=RequestBody.create(MediaType.parse("image.jpeg"),new File("/scard/a.jpg"));
Request request=new Request.Builder()
.url(testUrl)
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
第七部分:上传文件和文字
在OkHttp中实现上传文件是MultipartBuilder,比如我们现在需要更改用户的信息。用户更改了姓名和头像,头像是一个文件,我们这里就需要上传文件。我们上传的信息包括文件和表单。
private void uploadFileAndString() {
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
File file = new File("/scard/a.png");
//"application/octet-stream":传进去2进制流数据,流数据就包括文件和表单
RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
MultipartBody multipartBody = new MultipartBody.Builder()
//设置为form表单的类型
.setType(MultipartBody.FORM)
//name 和值
.addFormDataPart("name", "wangdidi")
//传入image字段,取名为"test.png"
.addFormDataPart("image", "test.png", fileBody).build();
Request request = new Request.Builder()
.post(multipartBody)
.url(testUrl).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}