単純なコールバックを作ってみる

##〇概要
Androidアプリでアーキテクチャーが複雑化してくると非同期の情報を行うクラスとそれを使うクラスが分かれてきます。
そうなると非同期で得たデータを取得したタイミングで別クラスに教えてあげなければならないわけですが結構面倒。
というわけで、サポートライブラリのAsyncTaskLoaderとかイベントバスを扱うライブラリ(EventBusやRxJavaなど）が色々あるわけですが、インターフェースを利用した原始的なコールバックの作り方の情報があまりなかったのでまとめてみました。

##〇サンプルソース
[GitHub](https://github.com/KIRIN3git/Callback)

##〇クラス一覧

###MainActivity
・メインクラス
・TasksRepositoryとTasksBackgroundDataSourceのインスタンスを生成。
・シンプルにするためにViewの表示関数もここに入れてあります。

###TasksRepository
・データを保持して操作するクラス。
・生成時にTasksBackgroundDataSourceのインスタンスを取得しています。
・データ取得の依頼をTasksBackgroundDataSourceに投げたり、コールバックを受け取りMainActivityに表示の依頼を投げる。

###TasksBackgroundDataSource
・非同期でデータを持ってくるクラス。
・TasksDataSourceインターフェースをimplementsしている。
・（ネットワークからデータを持ってくる処理を書くと処理が煩雑になるので、別スレッド立ててデータ埋め込んでいるだけ）

###TasksDataSource
・データ取得の処理関係をまとめたインターフェース。

###Task
・取得した値を管理するデータクラス。

#〇コールバック部分抜粋
（注）理解しやすいために上のクラス一覧とは逆順に記載

データ取得の関数とコールバックとして呼ばれる関数を定義

```java:TasksDataSource
public interface TasksDataSource {

    // コールバックとして呼ばれる関数
    interface LoadTasksCallback {
        void onTasksLoaded(List<Task> tasks);
        void onDataNotAvailable();
    }

    // データ取得関数（別に書かなくてよいがまとめて書いておく）
    void getTasks(@NonNull LoadTasksCallback callback);
}
```

データ取得関数getTasksを実装
取得後はコールバック関数を呼んであげる

```java:TasksBackgroundDataSource 
public class TasksBackgroundDataSource implements TasksDataSource {

    @Override
    public void getTasks(@NonNull final LoadTasksCallback callback) {

        final Handler handler = new Handler();

        // スレッド立ち上げ
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                 // Handlerを使用してメインスレッドに処理を依頼する（View更新のため）
                 handler.post(new Runnable() {
                     @Override
                     public void run() {

                         // データ取得
                         //　　・
                         //　　・

                         if (tasks.isEmpty()) {
                             // データがない時の処理
                             callback.onDataNotAvailable();

                         } else {
                             // データがあった時の処理
                             callback.onTasksLoaded(tasks);
                         }
                     }
                 });

            }
        });
        thread.start();
    }
}
```

TasksBackgroundDataSourceのgetTaskを呼び出して引数にLoadTasksCallbackのインスタンスを生成して呼び出してほしい関数を実装して渡す。

```java:TasksRepository
        mTasksBackgroundSource.getTasks(new TasksDataSource.LoadTasksCallback() {
            // データ取得後に呼ばれる処理（データありの時）
            @Override
            public void onTasksLoaded(List<Task> tasks) {
                MainActivity.showTextMsg(changeTasksToString(tasks));
            }
            // データ取得後に呼ばれる処理（データなしの時）
            @Override
            public void onDataNotAvailable() {
                Log.w("DEBUG_DATA","TaskRepository onDataNotAvailable");
            }
        });
```

#〇まとめ
結局はこれ呼んどいてね！ってデータ取得する関数に処理を実装したインスタンスを投げてるだけですが、それを実現するための設計が複雑ですね。
これはGoogleのMVPサンプルを元につくったのですが、そこでは
PresenterがRepositoryのgetTaskを呼び、そうするとDataSourceのgetTaskが呼ばれてと、数珠つなぎでcallbackが呼ばれていくという仕組みでした。
取得先も増えてくるとわけわからなくなってくるので、やっぱりライブラリを使いましょうということですね。
とりあえず基本をまとめてみました。

#〇参考
[android/architecture-samples](
https://github.com/android/architecture-samples/tree/todo-mvp)