前言: 在过去,Android上发送HTTP请求一般有两种方式:HttpURLConnection和HttpClient,由于HttpClient存在的API数量过多,扩展困难等缺点,在Android6.0系统中,HttpClient的功能被完全移除了。
而 OkHttp 是由Square公司开发的,OkHttp在接口封装上做的简单易用,比起原生的HttpURLConnection,可以说是有过之而无不及,现在已经成为了广大Android开发者首选的网络通信库。
使用HttpURLConnection进行网络请求详解请看这篇文章
同步请求与异步请求的概念:
简单地说,同步就是发出一个请求后什么事都不做,一直等待请求返回后才会继续做事;异步就是发出请求后继续去做其他事,这个请求处理完成后会通知你,这时候就可以处理这个回应了。
写了个Demo去理解Okhttp中的get同步请求与异步请求,和post同步请求与异步请求
1.get的同步请求,其中的讲解,已经在代码中注释了出来。
//get同步请求 public void getSync(View view) { //在Android 中完成网络请求必须在子线程中完成 new Thread(new Runnable() { @Override public void run() { OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url("http://www.httpbin.org/get?a=1&b=2").build(); //准备好请求的Code对象 Call call = okHttpClient.newCall(request); try { //同步请求要创建子线程,是因为execute()方法,会阻塞后面代码的执行 //只有执行了execute方法之后,得到了服务器的响应response之后,才会执行后面的代码 //所以同步请求要在子线程中完成 Response response = call.execute(); //把服务器给我们响应的字符串数据打印出来 Log.i(TAG,"getSync:"+response.body().string()); } catch (IOException e) { e.printStackTrace(); } } }).start(); }
2.get异步请求:
//get的异步请求 public void getAsync(View view) { //定义okhttp对象 OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url("http://www.httpbin.org/get?a=1&b=2").build(); Call call = okHttpClient.newCall(request); //异步请求:不用创建子线程 //enqueue()并不会阻塞代码的执行,不需要与服务器请求完成之后,才会执行后面的代码 //而且enqueue内部会为我们创建子线程 call.enqueue(new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { } @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { Log.i("TAG", "onResponse: " + (Looper.getMainLooper().getThread() == Thread.currentThread()));//为false 表示这是在子线程,需要切换到主线程才能操作UI if (response.isSuccessful()){ Log.i(TAG,"getAsync:"+response.body().string()); } } }); }
3.post同步请求:
//post同步请求 public void postSync(View view) { new Thread(new Runnable() { @Override public void run() { OkHttpClient okHttpClient = new OkHttpClient(); //post请求规定,把参数放在请求体里面,用form表单的方式来添加我们的请求体 FormBody formBody = new FormBody.Builder().add("a", "10000").add("b", "15000").build(); Request request = new Request.Builder().url("http://www.httpbin.org/post") .post(formBody) .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); Log.i(TAG,"postSync:"+response.body().string()); } catch (IOException e) { e.printStackTrace(); } } }).start(); }
4.post的异步请求:
//post异步请求 public void postAsync(View view) { OkHttpClient okHttpClient = new OkHttpClient(); FormBody formBody = new FormBody.Builder().add("a", "1000").add("b", "2000").build(); Request request = new Request.Builder().url("http://www.httpbin.org/post") .post(formBody) .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { } @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { Log.i("TAG", "onResponse: " + (Looper.getMainLooper().getThread() == Thread.currentThread()));//为false 表示这是在子线程,需要切换到主线程才能操作UI if (response.isSuccessful()){ Log.i(TAG,"postAsync:"+response.body().string()); } } }); }
上面用到的http服务器是公用的,需要的拿去用:地址www.httpbin.org/
新增:
一、 使用OkHttp 上传图片到服务器
private void UpLoadImage(String pictPath, String fileName) { //参数1:图片路径 参数2:图片名称 new Thread(new Runnable() { @Override public void run() { String url = "具体的URL地址"; //定义OkHttp OkHttpClient okHttpClient = new OkHttpClient(); MediaType JSON = MediaType.parse("multipart/form-data"); //定义请求体 RequestBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", fileName, RequestBody.create(JSON, new File(pictPath)))//addFormDataPart方法的第一个参数是key值,第二个参数是上传文件的名字,第三个参数是需要上传的文件 .build(); try { //执行OkHttp Request request = new Request.Builder() .post(body) .url(url) .build(); Response response = okHttpClient.newCall(request).execute(); String ss = response.body().string(); ResultMsg resultMsg = new Gson().fromJson(ss, ResultMsg.class); if (resultMsg.Result.equals("1")) { Looper.prepare(); Toast.makeText(ChangeInformationActivity.this, "图片上传成功!", Toast.LENGTH_SHORT).show(); Looper.loop(); } else { Looper.prepare(); Toast.makeText(ChangeInformationActivity.this, resultMsg.Message, Toast.LENGTH_SHORT).show(); Looper.loop(); } } catch (Exception e) { e.printStackTrace(); } } }).start(); }
二、 使用OkHttp 通过GET异步请求从服务器获取图片,下载到手机图库中,代码如下:
btn_save_image.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //申请读取或修改存储卡的权限 //对于共享区间写入的权限,在API29 Android系统10之前是需要申请的 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(OkHttpActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(OkHttpActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } else { SaveImage(); } } else { SaveImage(); } } });
SaveImage()方法实现从服务器下载一张图片,保存到图库中的功能:
//定义OkHttp OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url("https://cdn.pixabay.com/photo/2021/12/13/15/14/flowers-6868494_960_720.jpg") .build(); Call call = okHttpClient.newCall(request); //进行GET的异步请求 call.enqueue(new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { //没有网络的情况下,会回调这个方法 Log.e(TAG, "onFailure: " + "失败"); } @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { //当前就是子线程所以不用再开启子线程了 InputStream inputStream = response.body().byteStream(); //之后包装成处理流,提高流的读取 BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); BufferedOutputStream bufferedOutputStream = null; try { //保存到图库的URI Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues()); OutputStream outputStream = getContentResolver().openOutputStream(uri); bufferedOutputStream = new BufferedOutputStream(outputStream); //定义每次读取的字节数 byte[] buffer = new byte[1024 * 8]; int len; int length = 0; while ((len = bufferedInputStream.read(buffer)) != -1) { bufferedOutputStream.write(buffer, 0, len); length += len; } Log.i(TAG, "length: " + length); } catch (IOException e) { e.printStackTrace(); } finally { try { if (bufferedOutputStream != null) { bufferedOutputStream.close(); } if (bufferedInputStream != null) { bufferedInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } }); }
以上就是Okhttp框架的简单实用~,如有不当之处,还望各位网友加以指正!