blog.petitviolet.net

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

2015-07-05

QiitaJavaAndroid

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 する、みたいにしても良いかもしれない

from: https://qiita.com/petitviolet/items/8135a654901c73325fc0