【发布时间】:2014-08-06 11:03:21
【问题描述】:
我创建了一个帮助类来处理我的应用程序中的所有 http 调用。它是一个简单的 okhttp 单例包装器,看起来像这样(我省略了一些不重要的部分):
public class HttpUtil {
private OkHttpClient client;
private Request.Builder builder;
...
public void get(String url, HttpCallback cb) {
call("GET", url, cb);
}
public void post(String url, HttpCallback cb) {
call("POST", url, cb);
}
private void call(String method, String url, final HttpCallback cb) {
Request request = builder.url(url).method(method, method.equals("GET") ? null : new RequestBody() {
// don't care much about request body
@Override
public MediaType contentType() {
return null;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
}
}).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, Throwable throwable) {
cb.onFailure(null, throwable);
}
@Override
public void onResponse(Response response) throws IOException {
if (!response.isSuccessful()) {
cb.onFailure(response, null);
return;
}
cb.onSuccess(response);
}
});
}
public interface HttpCallback {
/**
* called when the server response was not 2xx or when an exception was thrown in the process
* @param response - in case of server error (4xx, 5xx) this contains the server response
* in case of IO exception this is null
* @param throwable - contains the exception. in case of server error (4xx, 5xx) this is null
*/
public void onFailure(Response response, Throwable throwable);
/**
* contains the server response
* @param response
*/
public void onSuccess(Response response);
}
}
然后,在我的主要活动中,我使用这个助手类:
HttpUtil.get(url, new HttpUtil.HttpCallback() {
@Override
public void onFailure(Response response, Throwable throwable) {
// handle failure
}
@Override
public void onSuccess(Response response) {
// <-------- Do some view manipulation here
}
});
onSuccess在代码运行时抛出异常:
android.view.ViewRootImpl$CalledFromWrongThreadException: 只有 创建视图层次结构的原始线程可以触及其视图。
据我了解,Okhttp 回调在主线程上运行,为什么会出现此错误?
** 顺便说一句,我创建了 HttpCallback 接口来包装 Okhttp 的 Callback 类,因为我想改变 onResponse 和 onFailure 的行为,这样我就可以统一处理失败响应的逻辑由于 i/o 异常和由于服务器问题导致的响应失败。
谢谢。
【问题讨论】:
-
Android 网络活动无法在主线程上运行。我没有使用 Okhttp 的经验,但我很确定您在单独的线程上。
-
我认为 Okhttp 在单独的线程上处理网络 io 并在主线程上回调。根据@jake-wharton 的创作者之一stackoverflow.com/a/21010181/599912 的说法,至少这就是改造的原因
-
我明白了。我在他们的documentation 中找到了一个
Calback类。你可以尝试实现那个。 -
@TmKVU 我实际上在
client.newCall(request).enqueue()的匿名类中实现了它。我从来没有从主线程产生另一个线程,所以我怀疑 Okhttp 天生就是这样做的。我认为以某种方式控制没有被转移回主线程
标签: android multithreading okhttp