OkHttpがサンプルとして用意しているAsynchronous Getレシピのように、OkHttpをバックグラウンド通信に使用した時、Callback
クラスのonFailuer
とonResponse
はどちらもバックグラウンドで実行される
AndroidでOkHttpを使う場合、バックグラウンド通信しなければならない理由から、コールバックをメインスレッドで行いたい場合、毎回以下のように書く必要があった。
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// do something
}
});
非常にめんどくさいのと行数が無駄に増えるので、コールバックをメインスレッドで行いたい場合のコールバッククラスを実装した
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
インタフェースのonFailure
とonResponse
を実装して、実際の処理におけるコールバックの実装はonFail
とonSuccess
に書けばよい
これでonFailure
とonResponse
から勝手にメインスレッドでonFail
とonSuccess
が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する、みたいにしても良いかもしれない