ViewModel について

## 概要

ViewModel が導入される前は、Activity や Fragment に通信処理や色々な処理を実装していました。
別クラスに分離して、処理を分けたとしてもUIに情報を通知するためにコールバックをひたすら実装することが多かったです。
ViewModel が導入され、UIと切り離して実装でき、通知も LiveData を使うことで楽に実装出来るようになったので、サンプルを記載したいと思います。

## ViewModel 導入前
例えば、AsyncTask で、UIと重い処理をクラスで分けた場合、下記のような実装するかと思います。
UIで、CallBackを受け取って、UI操作をします。

```java
public class MainTask extends AsyncTask<Void, Void, Long> {

  private Callback callback;
  public MainTask(CallBack callBack) {
    this.callback = callBack;
  }

  @Override
  protected Long doInBackground(Void... params) {
      // 重い処理
      if (ok) {
          return 0L;
      } else {
          return -1L;
      }
  }

  @Override
  protected void onPostExecute(Long result) {
    if (result == 0) {
      callback.onComplete();
    } else {
      callback.onError();
    }
  }

  public interface CallBackTask {
    public void onComplete();

    public void onError();
  }
}
```

## ViewModel 導入後
LiveData を postValue することで、UI に通知することが可能です。
導入前と比較するため同様な記載をしていますが、`MutableLiveData<Long>` として、値を渡せますので、resultの結果を渡せばいいことになります。そのため、本来なら onError は不要かと思います。

```java
public class MainViewModel extends ViewModel {
    private final MutableLiveData<Long> onComplete = new MutableLiveData<>();
    private final MutableLiveData<Long> onError = new MutableLiveData<>();

    public MainViewModel() {
        new MainTask().execute();
    }

    public LiveData<Long> getComplete() {
        return onComplete;
    }

    public LiveData<Long> getError() {
        return onError;
    }
    
    private class MainTask extends AsyncTask<Void, Void, Long> {

        @Override
        protected Long doInBackground(Void... params) {
            // 重い処理
            if (true) {
                return 0L;
            } else {
                return -1L;
            }
        }

        @Override
        protected void onPostExecute(Long result) {
            if (result == 0) {
                onComplete.postValue(result);
            } else {
                onError.postValue(result);
            }
        }
    }
}
```

UI側は、observe することで、変化があるたびに onChanged が呼ばれますので、それに適したUIを操作するだけになります。

```java
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        mViewModel.getComplete().observe(this, new Observer<Long>() {
            @Override
            public void onChanged(Long result) {
                // UI操作
            }
        });
        mViewModel.getError().observe(this, new Observer<Long>() {
            @Override
            public void onChanged(Long result) {
                // UI操作
            }
        });
    }
```

今までは、必要なコールバックを interface で定義して、都度渡す必要がありましたが、ViewModel 側でUIに通知したい場合は、postValue する。
UI側は、observe で変化が合った場合にUIを操作するだけになります。

## おまけ

ここまで対応すると、もう kotlin で実装した方がすごく楽になります。皆さんも kotlin を使っていきましょう。

```gradle
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.1'
```

```kotlin
class MainViewModel : ViewModel(), CoroutineScope {

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    private val job = Job()

    val data = MutableLiveData<Long>()

    fun getData() {
        launch {
            // 重い処理
            if (true) {
                data.postValue(0)
            } else {
                data.postValue(-1)
            }
        }
    }
}
```

```kotlin
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        viewModel.data.observe(this, Observer {
            // UI操作
            if (it == 0L) {

            } else {

            }
        })
    }
```