Android 我们是否需要使用HttpURLConnection';引发IOException时的错误流
根据Oracle Java的技术指南,当抛出Android 我们是否需要使用HttpURLConnection';引发IOException时的错误流,android,Android,根据Oracle Java的技术指南,当抛出IOException时,我们应该使用HttpURLConnection的错误流 你能做些什么来维持生命?不要放弃连接 通过忽略响应体。这样做可能会导致TCP空闲 连接。当它们不存在时,需要进行垃圾收集 引用时间更长 如果getInputStream()成功返回,请读取整个响应 身体 从HttpURLConnection调用getInputStream()时,如果 IOException发生时,捕获异常并调用getErrorStream()以 获取响
IOException
时,我们应该使用HttpURLConnection
的错误流
你能做些什么来维持生命?不要放弃连接
通过忽略响应体。这样做可能会导致TCP空闲
连接。当它们不存在时,需要进行垃圾收集
引用时间更长
如果getInputStream()成功返回,请读取整个响应
身体
从HttpURLConnection调用getInputStream()时,如果
IOException发生时,捕获异常并调用getErrorStream()以
获取响应主体(如果有)
读取响应主体会清理连接,即使您没有
对响应内容本身感兴趣。但是如果反应体是
长,你不感兴趣的其余部分后,看到了
开始时,可以关闭InputStream。但是你需要意识到
可能会有更多的数据。因此,连接可能不正确
可以重新使用
以下是符合上述建议的代码示例:
下面是代码示例
try {
URL a = new URL(args[0]);
URLConnection urlc = a.openConnection();
is = conn.getInputStream();
int ret = 0;
while ((ret = is.read(buf)) > 0) {
processBuf(buf);
}
// close the inputstream
is.close();
} catch (IOException e) {
try {
respCode = ((HttpURLConnection)conn).getResponseCode();
es = ((HttpURLConnection)conn).getErrorStream();
int ret = 0;
// read the response body
while ((ret = es.read(buf)) > 0) {
processBuf(buf);
}
// close the errorstream
es.close();
} catch(IOException ex) {
// deal with the exception
}
}
这是否适用于Android平台?因为我在大多数Android代码示例中都没有看到这种技术。如果您对向用户显示错误消息不感兴趣,请关闭
输入流
或在中调用HttpURLConnection
上的断开连接
,而不读取错误消息。这是您在大多数示例中看到的
在浏览HttpURLConnection的实现时,我在其中一篇文章中遇到了以下评论。这可能就是为什么在不读取所有数据的情况下关闭连接的原因
当连接意外关闭时,应调用此命令
使缓存项无效并阻止HTTP连接
重复使用。HTTP消息以串行方式发送,因此无论何时
无法读取完成,无法读取后续消息
必须放弃和连接中的任何一个
根据Android实现的HttpURLConnection
,如果出现异常:
- 如果未读取错误并且关闭了
InputStream
,则连接将被视为不可重用并关闭李>
- 如果读取错误,然后关闭
InputStream
,则连接将被视为可重用,并添加到连接池中
在下图中可以看到,只要读取了所有数据,变量connection
和connectionReleased
就分别设置为null
和true
。请注意,getErrorStream
返回InputStream
,因此它在异常场景中也有效
代码分析:让我们看一看专门的InputStream
实现。以下是close
方法的实现:
@Override public void close() throws IOException {
if (closed) {
return;
}
closed = true;
if (bytesRemaining != 0) {
unexpectedEndOfInput();
}
}
protected final void unexpectedEndOfInput() {
if (cacheRequest != null) {
cacheRequest.abort();
}
httpEngine.release(false);
}
实例变量byteslaining
包含要读取的InputStream
上仍然可用的字节数。以下是方法实现:
@Override public void close() throws IOException {
if (closed) {
return;
}
closed = true;
if (bytesRemaining != 0) {
unexpectedEndOfInput();
}
}
protected final void unexpectedEndOfInput() {
if (cacheRequest != null) {
cacheRequest.abort();
}
httpEngine.release(false);
}
下面是方法的实现。在HttpURLConnection
实例上调用disconnect
,将调用此release
方法,并将false
作为参数。
最后一次if
检查可确保连接是否需要关闭或添加到连接池中以供重用。
public final void release(boolean reusable) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
IoUtils.closeQuietly(responseBodyIn);
}
if (!connectionReleased && connection != null) {
connectionReleased = true;
// We cannot reuse sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reusable = false;
}
// If the headers specify that the connection shouldn't be reused, don't reuse it.
if (hasConnectionCloseHeader()) {
reusable = false;
}
if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
reusable = false;
}
if (reusable && responseBodyIn != null) {
// We must discard the response body before the connection can be reused.
try {
Streams.skipAll(responseBodyIn);
} catch (IOException e) {
reusable = false;
}
}
if (!reusable) {
connection.closeSocketAndStreams();
connection = null;
} else if (automaticallyReleaseConnectionToPool) {
HttpConnectionPool.INSTANCE.recycle(connection);
connection = null;
}
}
}
您共享的代码处理IOException,读取并关闭错误流,确保连接可重用,并将其添加到连接池中。从InputStream
读取所有数据时,连接将添加到连接池中。以下是fixedlenghthinputstream
的read
方法实现:
@Override public int read(byte[] buffer, int offset, int count) throws IOException {
Arrays.checkOffsetAndCount(buffer.length, offset, count);
checkNotClosed();
if (bytesRemaining == 0) {
return -1;
}
int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
if (read == -1) {
unexpectedEndOfInput(); // the server didn't supply the promised content length
throw new IOException("unexpected end of stream");
}
bytesRemaining -= read;
cacheWrite(buffer, offset, read);
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}
当byteslaining
变量变为0时,调用该变量,该变量将进一步调用release
方法和true
参数,以确保连接被池化
protected final void endOfInput(boolean reuseSocket) throws IOException {
if (cacheRequest != null) {
cacheBody.close();
}
httpEngine.release(reuseSocket);
}
如果它是为Java编写的,那么它是为Android平台绑定的。我在Android中看到的HttpURLConnection示例只是在finally块中执行disconnect()
。从文档中,“断开连接会释放连接所持有的资源,以便它们可以关闭或重新使用。”我想没有“保持活动”。这可能是你问题的答案,我已经在下面的回答中写下了我的想法。如果您需要进一步澄清,请告诉我。