OkHttpのメインスレッドコールバックの実装

OkHttpがサンプルとして用意しているAsynchronous Getレシピのように、OkHttpをバックグラウンド通信に使用した時、CallbackクラスのonFailueronResponseはどちらもバックグラウンドで実行される

AndroidでOkHttpを使う場合、バックグラウンド通信しなければならない理由から、コールバックをメインスレッドで行いたい場合、毎回以下のように書く必要があった。

new Handler(Looper.getMainLooper()).post(new Runnable() {

@Override
public void run() {
// do something
}
});

非常にめんどくさいのと行数が無駄に増えるので、コールバックをメインスレッドで行いたい場合のコールバッククラスを実装した


MainThreadCallback.java

public abstract class MainThreadCallback implements Callback {

private static final String TAG = MainThreadCallback.class.getSimpleName();

abstract public void onFail(final Exception exception);

abstract public void onSuccess(final JsonObject responseBody);

@Override
public void onFailure(final Call call, final IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
e.printStackTrace();
onFail(e);
}
});
}

@Override
public void onResponse(Call call, final Response response) throws IOException {
if (!response.isSuccessful() || response.body() == null) {
onFailure(response.request(), new IOException("Failed"));
return;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JsonObject responseBody = new Gson().fromJson(response.body().string(), JsonObject.class);
onSuccess(responseBody);
} catch (IOException e) {
e.printStackTrace();
onFailure(response.request(), new IOException("Failed"));
}
}
});
}

private void runOnUiThread(Runnable task) {
new Handler(Looper.getMainLooper()).post(task);
}
}


内部的にCallbackインタフェースのonFailureonResponseを実装して、実際の処理におけるコールバックの実装はonFailonSuccessに書けばよい

これでonFailureonResponseから勝手にメインスレッドでonFailonSuccessがcallされる

これで、コールバックをメインスレッドで行いたい場合はCall#enqueueの引数にMainThreadCallbackを与えるだけで実現できる

client.newCall(request).enqueue(new MainThreadCallback() {

@Override
public void onFail(Exception e) {
e.printStackTrace();
}

@Override
public void onSuccess(JsonObject responseBody) throws IOException {
someTextView.setText(responseBody.toString());
}
});

必要であれば、メインスレッドで行うメソッドとワーカースレッドで行うメソッドを両方抽象メソッドとして用意しておいて両方callする、みたいにしても良いかもしれない