Okhttp在主线程上回应callback
我创build了一个帮助器类来处理我的应用程序中的所有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
引发exception:
android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创build视图层次结构的原始线程可以触及其视图。
从我的理解,Okhttpcallback运行在主线程,所以为什么我得到这个错误?
**正如旁注所示,我创build了HttpCallback
接口来包装Okhttp的Callback
类,因为我想改变onResponse
和onFailure
的行为,所以我可以统一处理由于I / Oexception而导致失败响应的逻辑以及由于服务器问题。
谢谢。
从我的理解,Okhttpcallback运行在主线程,所以为什么我得到这个错误?
这不是真的。 callback在后台线程上运行。 如果你想立即处理在UI中的东西,你将需要张贴到主线程。
既然你已经有一个callback包装,你可以在你的助手内部做这个,所有的HttpCallback
方法都在主线程上调用。
正如杰克·沃顿(Jake Wharton)所build议的那样,我必须明确地在主线程上运行callback。
所以我用Runnable
将调用封装到了callback中:
private void call(String method, String url, final HttpCallback cb) { ... client.newCall(request).enqueue(new Callback() { Handler mainHandler = new Handler(context.getMainLooper()); @Override public void onFailure(Request request,final Throwable throwable) { mainHandler.post(new Runnable() { @Override public void run() { cb.onFailure(null, throwable); } }); } @Override public void onResponse(final Response response) throws IOException { mainHandler.post(new Runnable() { @Override public void run() { if (!response.isSuccessful()) { cb.onFailure(response, null); return; } cb.onSuccess(response); } }); } }); }
我知道这是一个古老的问题,但最近我遇到了同样的问题。 如果您需要更新任何视图,则需要使用runOnUiThread()
或将结果发回主线程。
HttpUtil.get(url, new Callback() { //okhttp3.Callback @Override public void onFailure(Call call, IOException e) { /* Handle error **/ } @Override public void onResponse(Call call, Response response) throws IOException { String myResponse = response.body().string(); //Do something with response //... MyActivity.this.runOnUiThread(new Runnable() { @Override public void run() { //Handle UI here findViewById(R.id.loading).setVisibility(View.GONE); } }); } });