目前Android中的网络请求最主要的就是UrlConnection和OkHttp了。而UrlConnection听说在安卓4.4以后也在内部实现了OkHttp。网络上OkHttp的封装框架也挺多比如鸿羊大神的okhttputils。框架虽有很多,基础我们更是需要了解的 ,看他们都是封装的啥内容。首先先从其最基本的用法开始
OkHttp的用法步骤:
引入最新的gradle依赖
compile 'com.squareup.okhttp3:okhttp:3.5.0' compile 'com.squareup.okio:okio:1.11.0'
Get:
Post:
示例代码:(官方文档)
package com.chs.okhttpdemo; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.view.View; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.TimeUnit; import okhttp3.Call; import okhttp3.Callback; import okhttp3.FormBody; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okio.BufferedSink; public class MainActivity extends AppCompatActivity { public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8"); private static final MediaType MEDIA_TYPE_JPG = MediaType.parse("application/octet-stream"); OkHttpClient okHttpClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //1.拿到OkHttpClient对象 okHttpClient = new OkHttpClient.Builder(). connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); } public void doGet(View view) { //创建request对象 Request.Builder builder = new Request.Builder(); Request request = builder.get().url("http://192.168.1.63:8080/album/login?name=chs&password=123").build(); execute(request); } //post提交(表单)键值对 public void doPost(View view) { //拿到body的构建器 FormBody.Builder builder = new FormBody.Builder(); //添加参数 builder.add("name", "chs") .add("password", "123"); //拿到requestBody RequestBody requestBody = builder.build(); //创建request对象 Request request = new Request.Builder() .url("http://192.168.1.63:8080/album/login") .post(requestBody) .build(); execute(request); } //post提交String 这个API最好不要发送大于1M的字符串 public void doPostString(View view) { String postBody = "{name:chs,pwd:123}"; //创建requestBody RequestBody requestBody = RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody); //创建request Request request = new Request.Builder() .url("http://192.168.1.63:8080/album/login") .post(requestBody) .build(); execute(request); } //post提交流 public void doPostStream(View view) { RequestBody requestBody = new RequestBody() { @Override public MediaType contentType() { return MEDIA_TYPE_MARKDOWN; } @Override public void writeTo(BufferedSink sink) throws IOException { sink.writeUtf8("doPostStream/n"); sink.writeUtf8("{name:doPostStream,title:doPostStream}"); } }; Request request = new Request.Builder() .url("http://192.168.1.63:8080/album/login") .post(requestBody) .build(); execute(request); } //post提交File public void doPostFile(View view) { //图片在手机上的路径 String path = Environment.getExternalStorageDirectory().getPath()+"/BXT_SetPic/20170118/1484724630838.jpg"; LogUtil.i("path:"+path); File file = new File(path); //创建requestBody RequestBody requestBody = RequestBody.create(MEDIA_TYPE_MARKDOWN, file); Request request = new Request.Builder() .url("http://192.168.1.63:8080/album/login") .post(requestBody) .build(); execute(request); } //post提交Multipart 键值对和file一起提交 public void doPostMultipart(View view) { //图片在手机上的路径 String path = Environment.getExternalStorageDirectory().getPath()+"/BXT_SetPic/20170118/1484724630838.jpg"; LogUtil.i("pth:"+path); File file = new File(path); RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("name", "Square") .addFormDataPart("password", "1111") .addFormDataPart("image", "1484724630838.jpg", RequestBody.create(MEDIA_TYPE_JPG, file)) .build(); //封装一层来获取上传的进度 CountingRequestBody countRequestBody = new CountingRequestBody(requestBody, new CountingRequestBody.OnProgressListener() { @Override public void OnProgress(long byteWrite, long contentLength) { LogUtil.i(byteWrite+"/"+contentLength); } }); Request request = new Request.Builder() .url("http://192.168.1.63:8080/album/login") .post(countRequestBody) .build(); execute(request); } //下载 public void doDownLoad(View view) { //创建request对象 Request.Builder builder = new Request.Builder(); Request request = builder.get().url("http://192.168.1.63:8080/album//files/album.jpg").build(); //封装成一个请求的任务 Call call = okHttpClient.newCall(request); //同步的请求 Response response = call.execute(); // 执行请求(异步的请求) call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { LogUtil.i("请求失败:" + e.toString()); } @Override public void onResponse(Call call, Response response) throws IOException { LogUtil.i("请求成功:"); //总的长度 long totalLength = response.body().contentLength(); //下载的进度 long sum = 0; InputStream is = response.body().byteStream(); int len = 0; byte [] buff = new byte[1024]; File file = new File(Environment.getExternalStorageDirectory(),"album.jpg"); FileOutputStream os = new FileOutputStream(file); while ((len=is.read(buff))!=-1){ os.write(buff,0,len); sum+=len; LogUtil.i(sum+"/"+totalLength); } os.flush();; os.close(); is.close(); LogUtil.i("success"); } }); } private void execute(Request request) { //封装成一个请求的任务 Call call = okHttpClient.newCall(request); //同步的请求 Response response = call.execute(); // 执行请求(异步的请求) call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { LogUtil.i("请求失败:" + e.toString()); } @Override public void onResponse(Call call, Response response) throws IOException { LogUtil.i("请求成功:" + response.body().string()); } }); } }
因为RequestBody没有提供上传的进度,所以在上传的时候包装RequestBody用来计算上传的进度
package com.chs.okhttpdemo; import java.io.IOException; import okhttp3.MediaType; import okhttp3.RequestBody; import okio.Buffer; import okio.BufferedSink; import okio.ForwardingSink; import okio.Okio; import okio.Sink; /** * 作者:chs on 2017/1/19 16:05 * 邮箱:657083984@qq.com * 包装RequestBody用来计算上传的进度 */ public class ProgressRequestBody extends RequestBody { //真正的mRequestBody private RequestBody mRequestBody; //上传回调接口 private OnProgressListener mProgressListener; public ProgressRequestBody(RequestBody requestBody, OnProgressListener progressListener) { mRequestBody = requestBody; mProgressListener = progressListener; } public interface OnProgressListener { void OnProgress(long byteWrite,long contentLength); } @Override public MediaType contentType() { return mRequestBody.contentType(); } @Override public long contentLength() { try { return mRequestBody.contentLength(); } catch (IOException e) { return -1; } } @Override public void writeTo(BufferedSink sink) throws IOException { CountingSink countingSink = new CountingSink(sink); BufferedSink bufferedSink = Okio.buffer(countingSink); mRequestBody.writeTo(bufferedSink); bufferedSink.flush(); } protected final class CountingSink extends ForwardingSink{ private long byteWrite; public CountingSink(Sink delegate) { super(delegate); } @Override public void write(Buffer source, long byteCount) throws IOException { super.write(source, byteCount); byteWrite+=byteCount; mProgressListener.OnProgress(byteWrite,contentLength()); } } }