OkHttp取消调用回调失败
Callback failure for canceled call in OkHttp
在 OkHttp(2.4 版)客户端中取消排队的调用有时会抛出 Callback failure for canceled call to http://...
并且两个回调方法都不会执行。
因为我必须向用户提供正面或负面的反馈,所以不能接受这样的回调。我怎样才能解决这个错误?
我创建了带有两个按钮(一个用于开始下载请求,另一个用于取消下载请求)、文本视图和图像视图的测试应用程序,大部分时间都显示错误。最初,我在单击“取消”按钮时发现错误,但是使用带有处理程序的自动单击对于成功重复错误更为有效。
package com.test.httptest;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.IOException;
public class MainActivity extends Activity
{
final private OkHttpClient client = new OkHttpClient();
private Object cancel = new Object();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onHttpClick(View v)
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText("start");
downloadImage("http://httpbin.org/image/jpeg");
// simulate cancel click
new Handler().postDelayed(new Runnable()
{
public void run()
{
onCancelClick(null);
}
}, 380);
}
public void onCancelClick(View v)
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText("canceling");
client.cancel(cancel);
}
public void downloadImage(String url)
{
Request request = new Request.Builder()
.tag(cancel)
.url(url)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback()
{
String result = "";
@Override
public void onFailure(Request request, IOException e)
{
result = e.getMessage();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText(result);
}
});
}
@Override
public void onResponse(Response response) throws IOException
{
if (response.isSuccessful())
{
final byte[] input = response.body().bytes();
final int len = (int) response.body().contentLength();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText("completed");
ImageView iv = (ImageView) findViewById(R.id.image_view);
Bitmap bm = BitmapFactory.decodeByteArray(input, 0, len);
iv.setImageBitmap(bm);
}
});
}
else
{
result = response.body().string();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText(result);
}
});
}
}
});
}
}
Logcat:
08-24 23:00:13.151 14403-14451/com.test.httptest I/OkHttpClient﹕ Callback failure for canceled call to http://httpbin.org/...
java.net.SocketException: Socket closed
at libcore.io.Posix.recvfromBytes(Native Method)
at libcore.io.Posix.recvfrom(Posix.java:141)
at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
at libcore.io.IoBridge.recvfrom(IoBridge.java:506)
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
at java.net.PlainSocketImpl.access[=11=]0(PlainSocketImpl.java:46)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
at okio.Okio.read(Okio.java:137)
at okio.AsyncTimeout.read(AsyncTimeout.java:211)
at okio.RealBufferedSource.read(RealBufferedSource.java:50)
at com.squareup.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:418)
at okio.Buffer.writeAll(Buffer.java:956)
at okio.RealBufferedSource.readByteArray(RealBufferedSource.java:92)
at com.squareup.okhttp.ResponseBody.bytes(ResponseBody.java:57)
at hr.artplus.httptestm.MainActivity.onResponse(MainActivity.java:87)
at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:170)
at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
它是调用你的onResponse
方法。它在堆栈跟踪中显示为
at hr.artplus.httptestm.MainActivity.onResponse(MainActivity.java:87)
发生的事情是你在这一行得到了一个 IOException
--
final byte[] input = response.body().bytes();
可能是因为在您阅读时由于取消,流已关闭。您的代码让异常传播回 Callback
class,它不会发出另一个回调,因为它已经调用了 onResponse
.
您可以捕获异常并在回调中处理它 --
if (response.isSuccessful()) {
try {
final byte[] input = response.body().bytes();
final int len = (int) response.body().contentLength();
} catch (IOException e) {
// Signal to the user failure here, re-throw the exception, or
// whatever else you want to do on failure
}
...
在 OkHttp(2.4 版)客户端中取消排队的调用有时会抛出 Callback failure for canceled call to http://...
并且两个回调方法都不会执行。
因为我必须向用户提供正面或负面的反馈,所以不能接受这样的回调。我怎样才能解决这个错误?
我创建了带有两个按钮(一个用于开始下载请求,另一个用于取消下载请求)、文本视图和图像视图的测试应用程序,大部分时间都显示错误。最初,我在单击“取消”按钮时发现错误,但是使用带有处理程序的自动单击对于成功重复错误更为有效。
package com.test.httptest;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.IOException;
public class MainActivity extends Activity
{
final private OkHttpClient client = new OkHttpClient();
private Object cancel = new Object();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onHttpClick(View v)
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText("start");
downloadImage("http://httpbin.org/image/jpeg");
// simulate cancel click
new Handler().postDelayed(new Runnable()
{
public void run()
{
onCancelClick(null);
}
}, 380);
}
public void onCancelClick(View v)
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText("canceling");
client.cancel(cancel);
}
public void downloadImage(String url)
{
Request request = new Request.Builder()
.tag(cancel)
.url(url)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback()
{
String result = "";
@Override
public void onFailure(Request request, IOException e)
{
result = e.getMessage();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText(result);
}
});
}
@Override
public void onResponse(Response response) throws IOException
{
if (response.isSuccessful())
{
final byte[] input = response.body().bytes();
final int len = (int) response.body().contentLength();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText("completed");
ImageView iv = (ImageView) findViewById(R.id.image_view);
Bitmap bm = BitmapFactory.decodeByteArray(input, 0, len);
iv.setImageBitmap(bm);
}
});
}
else
{
result = response.body().string();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
TextView tv = (TextView) findViewById(R.id.text_view);
tv.setText(result);
}
});
}
}
});
}
}
Logcat:
08-24 23:00:13.151 14403-14451/com.test.httptest I/OkHttpClient﹕ Callback failure for canceled call to http://httpbin.org/...
java.net.SocketException: Socket closed
at libcore.io.Posix.recvfromBytes(Native Method)
at libcore.io.Posix.recvfrom(Posix.java:141)
at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
at libcore.io.IoBridge.recvfrom(IoBridge.java:506)
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
at java.net.PlainSocketImpl.access[=11=]0(PlainSocketImpl.java:46)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
at okio.Okio.read(Okio.java:137)
at okio.AsyncTimeout.read(AsyncTimeout.java:211)
at okio.RealBufferedSource.read(RealBufferedSource.java:50)
at com.squareup.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:418)
at okio.Buffer.writeAll(Buffer.java:956)
at okio.RealBufferedSource.readByteArray(RealBufferedSource.java:92)
at com.squareup.okhttp.ResponseBody.bytes(ResponseBody.java:57)
at hr.artplus.httptestm.MainActivity.onResponse(MainActivity.java:87)
at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:170)
at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
它是调用你的onResponse
方法。它在堆栈跟踪中显示为
at hr.artplus.httptestm.MainActivity.onResponse(MainActivity.java:87)
发生的事情是你在这一行得到了一个 IOException
--
final byte[] input = response.body().bytes();
可能是因为在您阅读时由于取消,流已关闭。您的代码让异常传播回 Callback
class,它不会发出另一个回调,因为它已经调用了 onResponse
.
您可以捕获异常并在回调中处理它 --
if (response.isSuccessful()) {
try {
final byte[] input = response.body().bytes();
final int len = (int) response.body().contentLength();
} catch (IOException e) {
// Signal to the user failure here, re-throw the exception, or
// whatever else you want to do on failure
}
...