如何在OkHttpClient获取响应后关闭HTTP客户端连接?
我正在使用OkHttpClient发送请求,希望确保在收到响应后关闭连接。我查找了client对象的disconnect或close方法但未找到,请问该如何在收到响应后关闭此连接?
以下是我的请求代码:
public class WebserviceCall extends AsyncTask<Void,Void,String> { // interface for response AsyncResponse delegate; private final MediaType URLENCODE = MediaType.parse("application/json;charset=utf-8"); ProgressDialog dialog; Context context; String dialogMessage; boolean showDialog = true; String URL; String jsonBody; private OkHttpClient client; public WebserviceCall(Context context, String URL, String jsonRequestBody, String dialogMessage, boolean showDialog, AsyncResponse delegate){ this.context = context; this.URL = URL; this.jsonBody = jsonRequestBody; this.dialogMessage = dialogMessage; this.showDialog = showDialog; this.delegate = delegate; } @Override protected void onPreExecute() { super.onPreExecute(); if(Utils.isNetworkAvailable(context)) { if (showDialog) { /*dialog = new ProgressDialog(context); dialog.setMessage(dialogMessage); dialog.show();*/ } } else { Utils.showDialog(context, context.getString(R.string.networkWarning)); } } @Override protected String doInBackground(Void... params) { // creating okhttp client client = new OkHttpClient(); // client.setConnectTimeout(10L, TimeUnit.SECONDS); // creating request body RequestBody body; if(jsonBody != null) { body = RequestBody.create(URLENCODE, jsonBody); }else{ body = null; }; // creating request Request request = new Request.Builder() .post(body) .url(URL) .build(); // creating webserivce call and get response try { Response response = client.newCall(request).execute(); String res = response.body().string(); Log.d("myapp", res); return res; } catch (IOException e) { e.printStackTrace(); // Toast.makeText(context,"could not connect to server",Toast.LENGTH_LONG).show(); } return null; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); try { /*if ((dialog != null) && showDialog) { dialog.dismiss(); }*/ } catch (final IllegalArgumentException e) { // Handle or log or ignore } catch (final Exception e) { // Handle or log or ignore } finally { dialog = null; } if (s != null) { delegate.onCallback(s); } else { Log.d("myapp",getClass().getSimpleName()+": response null"); } } }
首先要明确:OkHttpClient默认会维护一个连接池,用于复用HTTP连接,空闲的连接会在超时后自动被回收,所以大多数情况下你不需要手动关闭连接,框架会自动帮你管理这部分资源。
不过针对你的代码和需求,有几个关键点需要注意:
确保ResponseBody被正确关闭
你当前代码中调用了response.body().string(),这个方法内部会自动读取并关闭ResponseBody的流,所以这一步已经正确释放了响应相关的资源。但如果你是用response.body().byteStream()或者response.body().charStream()这类方法,一定要手动关闭流,最好用Java的try-with-resources语法来自动处理:try (Response response = client.newCall(request).execute()) { try (ResponseBody body = response.body()) { String res = body.string(); Log.d("myapp", res); return res; } } catch (IOException e) { e.printStackTrace(); }主动关闭当前连接(而非复用)
如果你确实需要立即关闭当前连接,不让它回到连接池复用,可以通过Response对象获取连接并关闭:try { Response response = client.newCall(request).execute(); String res = response.body().string(); Log.d("myapp", res); // 主动关闭连接 if (response.connection() != null) { response.connection().close(); } return res; } catch (IOException e) { e.printStackTrace(); }优化OkHttpClient的使用
你现在每次在doInBackground里新建一个OkHttpClient实例,这会导致连接池无法复用连接,建议把OkHttpClient做成单例,比如:// 单例OkHttpClient private static final OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .build();这样所有请求共享同一个连接池,能提升性能,也更符合OkHttp的设计理念。
总结:如果只是想确保响应资源被释放,你的代码已经通过string()方法做到了;如果要主动关闭连接,用response.connection().close();另外要复用OkHttpClient实例,不要每次新建。
内容的提问来源于stack exchange,提问作者Sid

