LoginSignup
171
171

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-11-27

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

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

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

CafeSnapというアプリでは、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
こちらをなんとなく翻訳してみます。

notifyDataSetChanged()

final void notifyDataSetChanged()

データセットが変更されたことを、登録されているすべてのobserverに通知する。

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

notifyItemChanged(int position)

final void notifyItemChanged(int position)

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

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

Adapterの実装例
List<MyModel> _objects;

public int indexOf(MyModel object) {
    return _objects.indexOf(object);
}
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)

final void notifyItemChanged(int position, Object payload)

これはまだ使った経験のないメソッドですが、どうやら……
positionのitemをpayloadで渡したオブジェクトで交換してくれる、というものなのだと思います。
普段は、自分でaddAllみたいなメソッドを実装しなくても、Object渡したら交換できちゃうってことなのだと思います。

payloadで渡したUIオブジェクトの部分を更新できると言うもののようです。
詳しい実装方法は、こちらの記事に書いてありました!↓
RecyclerView の notifyItemChanged をもっと便利に使う

notifyItemInserted(int position)

final void notifyItemInserted(int position)

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

notifyItemMoved(int fromPosition, int toPosition)

final void notifyItemMoved(int fromPosition, int toPosition)

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

notifyItemRangeChanged(int positionStart, int itemCount)

final void notifyItemRangeChanged(int positionStart, int itemCount)

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

notifyItemRangeChanged(int positionStart, int itemCount, Object payload)

final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload)

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

このメソッドも使ったことないけど、payloadに入れたオブジェクトで更新してもらえるんだと思います。
違うのかな……???

payloadで渡したUIオブジェクトの部分を更新できると言うもののようです。
詳しい実装方法は、こちらの記事に書いてありました!↓
RecyclerView の notifyItemChanged をもっと便利に使う

notifyItemRangeInserted(int positionStart, int itemCount)

final void notifyItemRangeInserted(int positionStart, int itemCount)

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

notifyItemRangeRemoved(int positionStart, int itemCount)

final void notifyItemRangeRemoved(int positionStart, int itemCount)

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

notifyItemRemoved(int position)

final void notifyItemRemoved(int position)

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

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

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

171
171
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
171
171