LoginSignup
25
26

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-07-05

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

25
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
26