Android Architecture Components Room以外

<font color="#6ab244">Android Architecture Components</font>を使った[サンプル](http://qiita.com/u_nation/items/e1b2c8a7a066331950a3)を作るにあたって学んだことをメモ代わりに残していきたいと思います。
自分はそれぞれ単体でどう機能するのか理解し、その後組み合わせて使うことで理解が深まったので、それぞれ単体だとどういう使い方ができるのかを簡単に紹介してみたいと思います。

## ViewModel
今回触ってみて一番使うのが簡単な割に、嬉しい機能だと思ったのが**ViewModel**です。
気に入った点を挙げてみると、
### 1. 画面回転時のonDestroyを生き抜く

今まで**[Icepick](https://github.com/frankiesardo/icepick)**や**[Pikkel](https://github.com/yamamotoj/Pikkel)**を使って画面回転時の状態保存をしていた方が多いと思いますが、今後はViewModelを使用するとより簡単に状態保存ができます。

最小構成で簡単にその機能を試せるのは[**GoogleCodeLabs**のサンプルstep2](https://github.com/googlecodelabs/android-lifecycles/tree/master/app/src/main/java/com/example/android/lifecycles/step2)です。
気をつけるところは生成するときに直接newするのではなくViewModelProviders経由で取得するところくらいでしょうか。
サンプルでは**LifecycleActivity**を使用していますが、**AppCompatActivityやFragment**からでも使用可能です。

### 2. Fragment間で共有できる
`ViewModelProviders.of` に親Activityを渡してあげると子Fragment間でのデータ共有ができます。[拙作のサンプル](https://github.com/u-nation/arch-components-realm)からで申し訳ないのですが、以下のように書くことでMainViewModelを両Fragment間で共有することができます。

```kotlin
class BookMarkFragment : LifecycleFragment() {
    private val mainViewModel by lazy { ViewModelProviders.of(activity).get<MainViewModel>() }
}

class ArticleFragment : LifecycleFragment() {
    private val mainViewModel by lazy { ViewModelProviders.of(activity).get<MainViewModel>() }
}
```

### 3. 画面が破棄されるタイミングがわかる
これまではonCreateなどのライフサイクルイベントをPresenterなどへ渡し、Pub/Subの購読や解除を行なっていたのが、画面が破棄されるタイミングで**onClearedメソッド**が呼ばれるのでViewModel生成時に購読、破棄時に解除できるのでViewModelがライフサイクルを意識する必要がありません。

## Lifecycle
**ライフサイクルを持つActivityやFragment**(LifecycleOwner)が、**ライフサイクルイベントをフックしたい任意のオブジェクト**(LifecycleObserver)に指定されたライフサイクルイベントを伝えることができます。

例えばPresenterにライフサイクルイベントを伝えたい時は以下のように書きます。

* ライフサイクルイベントをフックするPresenterに**LifecycleObserver**をimplementsし、@OnLifecycleEventから任意のライフサイクルを伝える
* ライフサイクルオーナーとなるActivityやFragmentは**LifecycleActivity**,**LifecycleFragment**を継承し、**lifecycle.addObserver(LifecycleObserverImpl)**をする

```kotlin
class Presenter : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
    	// do something
    }
}

class MainActivity : LifecycleActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val presenter : Presenter = Presenter()
        lifecycle.addObserver(presenter)
}    
```

## LiveData
**LiveDataはLifecycleと共に使います。**  
EventBusやRxJavaのBehaviorSubjectのように、データ変更時に通知することができます。
これまでの通知機構との違いは

1. RxLifecycleなど使わずとも**ライフサイクルが安全な状態の時だけ通知してくれる**。
2. 一度購読したら解除を自動で行ってくれる。

これで忌々しいFragmentのIllegalStateExceptionも楽に回避できそうです。

こちらも最小構成だと[**GoogleCodeLabs**のサンプルstep3_solution](https://github.com/googlecodelabs/android-lifecycles/tree/master/app/src/main/java/com/example/android/lifecycles/step3_solution)が理解しやすかったです。

データに変更があった時はLiveDataのsetValueメソッドを使います。

```java:サンプルstep3_solution
// Update the elapsed time every second.
timer.scheduleAtFixedRate(new TimerTask() {
		@Override
       public void run() {
			final long newValue = (SystemClock.elapsedRealtime() - mInitialTime) / 1000;
			// setValue() cannot be called from a background thread so post to main thread.
			new Handler(Looper.getMainLooper()).post(new Runnable() {
				@Override
				public void run() {
					mElapsedTime.setValue(newValue);
				}
			});
		}
}, ONE_SECOND, ONE_SECOND);
```  
サンプルだとHandlerを使っていますが、非同期処理の場合はpostValueを使うことも可能です。


```java:サンプルstep3_solution
// Update the elapsed time every second.
timer.scheduleAtFixedRate(new TimerTask() {
		@Override
       public void run() {
			final long newValue = (SystemClock.elapsedRealtime() - mInitialTime) / 1000;
			mElapsedTime.postValue(newValue);
		}
}, ONE_SECOND, ONE_SECOND);
```  

## 雑まとめ
安全にデータ変更通知をさせてくれるのがLifecycleとLiveData、画面回転対応する場合はViewModel、LiveDataはViewModelで保持する。

次はRoomも使ってみます。
## お世話になった記事
[Android Architecture Components Lifecycle, LiveData and ViewModel 詳解](https://tech.recruit-mp.co.jp/mobile/post-12285/#ViewModel-8211-Activity)
[Android Architecture Components 感想](http://starzero.hatenablog.com/entry/2017/05/19/005437)
[Android Architecture Components ViewModel 和訳](http://qiita.com/aroe_lemon/items/9aa80042e6fc10d32d49)