petitviolet blog

    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