RecyclerView.Adapterのnotify系メソッド 〜 notifyDataSetChangedで…いいの？

#12月1日は「データセンターの日」とのことで……

[今日は何の日](http://www.nnh.to/12/01.html)によると、12月1日は「データセンターの日」という記念日だそうな。Data CenterとDeCemberが雰囲気似ているという理由から、ソフトバンクIDC（現IDCフロンティア）が制定したんだとか。

## というわけで、「データ」にまつわるAndroid

[CafeSnap](http://cafesnap.me/)というアプリでは、Design Support Libraryを使用して、マテリアルデザインを導入しつつあります。マテリアルデザインの設計思想では、これまでのOSより自由で、魅力的なモーションを用いたUIが、比較的簡単に実装できるようになりました。

今日は、マテリアル化をすすめる中で遭遇した、RecyclerViewに渡すデータの「更新」に関するメソッドを、まとめてみることにします。

# そもそもRecyclerViewって…

RecyclerViewは、しばしばGridViewやListViewなどの、データ一覧を表示するViewと比較されますが、RecyclerViewは少し違います。GridViewやListViewが、データを表示することに特化していると思いますが、RecyclerViewはリストのアイテムを操作する方に寄っているように思います。

# notifyDataSetChangedばかり使っていないか

とりあえずadapterに渡しているobjectにaddしたりaddAllしたら、**とりあえずnotifyDataSetChanged**してませんか。そもそもnotifyDataSetChangedは、**リスト全体を更新**するためのメソッド。**ページングのためのメソッドではない**。他に何かあるの。

# RecyclerView.Adapterのnotify系メソッド一覧

ListViewやGridViewなどありますが、今回はRecyclerViewのnotify系メソッドをまとめます。
今後のことも考えて、RecyclerViewを使えるようになるのは大事な気がしたので。

**[RecyclerView.Adapter | Android Developers](http://developer.android.com/intl/ja/reference/android/support/v7/widget/RecyclerView.Adapter.html)**
こちらをなんとなく翻訳してみます。


## notifyDataSetChanged()
```java
final void notifyDataSetChanged()
```
データセットが変更されたことを、登録されているすべてのobserverに通知する。

RecyclerViewに表示されているItem全体に更新をかけるようです。Item内でアニメーション（例えばフェードインとか）を使用しているViewがあると、すべてのItemのアニメーションが実行されます。

## notifyItemChanged(int position)
```java
final void notifyItemChanged(int position)
```
指定したpositionのitemが変更されたことを、登録されているすべてのobserverに通知する。

adapterに`indexOf()`とかメソッドを作っておくと、実装しやすくなったりします。

```java:Adapterの実装例
List<MyModel> _objects;

public int indexOf(MyModel object) {
    return _objects.indexOf(object);
}
```

```java:ActivityやFragment側の実装例
// 初期化済みとする
MyRecyclerViewAdapter _adapter;

// 仮に、Itemが変化したことを通知するコールバックがあったとして……
public void onItemChanged(MyModel object) {
    int position = _adapter.indexOf(object);
    _adapter.notifyItemChanged(position);
}
```

OnClickとかのリスナは、結局Adapterにつけるしかないのですかね、なんだか変な感じがしますが……。

## notifyItemChanged(int position, Object payload)
```java
final void notifyItemChanged(int position, Object payload)
```

これはまだ使った経験のないメソッドですが、~~どうやら……
`position`のitemを`payload`で渡したオブジェクトで交換してくれる、というものなのだと思います。
普段は、自分でaddAllみたいなメソッドを実装しなくても、Object渡したら交換できちゃうってことなのだと思います。~~
payloadで渡したUIオブジェクトの部分を更新できると言うもののようです。
詳しい実装方法は、こちらの記事に書いてありました！↓
[RecyclerView の notifyItemChanged をもっと便利に使う](https://qiita.com/ralph/items/e56844976117d9883e34)

## notifyItemInserted(int position)
```java
final void notifyItemInserted(int position)
```

指定したpositionに新しいitemが挿入されたことを、登録されているすべてのobserverに通知する。

## notifyItemMoved(int fromPosition, int toPosition)
```java
final void notifyItemMoved(int fromPosition, int toPosition)
```

`fromPosition`のitemが、`toPosition`へ移動したことを、登録されているすべてのobserverに通知する。

## notifyItemRangeChanged(int positionStart, int itemCount)
```java
final void notifyItemRangeChanged(int positionStart, int itemCount)
```
positionStartの位置からitemCountの範囲において、データの変更があったことを登録されているすべてのobserverに通知する。

## notifyItemRangeChanged(int positionStart, int itemCount, Object payload)
```java
final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload)
```
positionStartの位置からitemCountの範囲において、データの変更があったことを登録されているすべてのobserverに通知する。

このメソッドも使ったことないけど、~~payloadに入れたオブジェクトで更新してもらえるんだと思います。
違うのかな……？？？~~
payloadで渡したUIオブジェクトの部分を更新できると言うもののようです。
詳しい実装方法は、こちらの記事に書いてありました！↓
[RecyclerView の notifyItemChanged をもっと便利に使う](https://qiita.com/ralph/items/e56844976117d9883e34)

## notifyItemRangeInserted(int positionStart, int itemCount)
```java
final void notifyItemRangeInserted(int positionStart, int itemCount)
```

positionStartの位置からitemCountの範囲において、データの変更があったことを登録されているすべてのobserverに通知する。

## notifyItemRangeRemoved(int positionStart, int itemCount)
```java
final void notifyItemRangeRemoved(int positionStart, int itemCount)
```

`positionStart`を先頭に`itemCount`の範囲のitemがデータセットから削除されたことを、登録されているすべてのobserverに通知する。

## notifyItemRemoved(int position)
```java
final void notifyItemRemoved(int position)
```

指定したpositionに存在したitemがデータセットから削除されたことを、登録されたすべてのobserverに通知する。

このメソッドを呼ぶと、消えた行を埋めるようにアニメーションされてかっこいい！


こんな感じで。
みなさんのRecyclerView、RecyclerView.Adapter実装の参考になればと思います。