Okhttp callbacks in the main thread

I created a helper class to handle all of my HTTP calls in my application. This is a simple singleton shell for okhttp that looks like this (I omitted some non-essential parts):

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); } } 

Then in my main action I use this helper class:

 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 throws an exception when running the code:

android.view.ViewRootImpl $ CalledFromWrongThreadException: only the original thread that created the view hierarchy can touch its views.

From my point of view, Okhttp callbacks work in the main thread, so why can I get this error?

** Like the note, I created the HttpCallback interface for the Okhttp Callback class shell because I wanted to change the behavior of onResponse and onFailure so that I could combine the logic of processing failed responses due to i / o exceptions and failed responses due to server problems .

Thank.

+50
android multithreading
Jun 16 '14 at 15:07
source share
3 answers

From my point of view, Okhttp callbacks are triggered in the main thread, so why can I get this error?

This is not true. Callbacks are made in the background thread. If you want to immediately process something in the user interface, you will need to send a message to the main thread.

Since you already have a wrapper around the callback, you can do this inside your helper so that all the HttpCallback amenities HttpCallback called in the main thread for convenience.

+60
Jun 16 '14 at 17:22
source

As Jake Wharton suggested, I had to explicitly run callbacks in the main thread.

So, I wrapped the callbacks using Runnable as follows:

 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); } }); } }); } 
+36
Jun 16 '14 at 21:12
source

I know this is an old question, but lately I have run into the same problem. If you need to update any view, you will need to use runOnUiThread() or post the result to the main thread.

 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); } }); } }); 
+10
Jan 19 '16 at 15:19
source



All Articles