初めてGroupieを使ったからまとめました

AndroidのRecyclerViewを便利に扱わせてくれるライブラリ[Groupie][link2]。
勉強するにあたりgithubのexampleを参考したので、学んだことを共有したいので書きたいと思います。
様々な表示方法を実装した上でのポイントや疑問に思ったことをまとめるので、この記事を読んだだけで表示できるようになるといったものではないのでご了承ください。コードでの説明はありません。自分が実装したものを[githubのリポジトリ][link1]に載せてありますのでご確認いただけたら嬉しいです。
なお、まだまだ始めたばかりで簡単に使ったことしかない上に、調べたつもりではありますが個人の思想が勝手に広がっている可能性があるのでご注意いただきたいです。

## Groupieの要素について
### Adapter
- `groupAdapter = GroupAdapter<GroupieViewHoder>()`で生成する。
- この`groupAdapter`に`Item`や`Section`を追加することで簡単にリスト表示することができる。
- `add(Group)`,`addAll(List<Group>)`,`update(List<Group>)`などのメソッドを使って追加。

### Group
- `Item`や`Section`のことを指す。
- `Item`や`Section`にInterfaceとして実装されている。

### Item
- recyclerViewに入れる要素1つ1つを示す。
- `Item`ごとにlayoutを組んで、良い感じに`groupAdapter`に追加していくことで様々な画面を作ることができる。
- ItemクラスにてViewと値を結びつけたりどのlayoutを適用するか指定できる。

### Section
- 複数の`Item`をかたまりとして`Section`に追加し、その`Section`を`groupAdapter`に追加することができる。
- `Item`を塊でまとめて`Section`とすることでコードもまとまってくるのでしょうか...

<div align="center"> 
<img title='groupieイメージ図.jpg' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304276/0548ce0c-594e-764b-1f0b-1c03d1e151ef.jpeg' width="590" data-meta='{"width":590,"height":360}'>
</div>


## 実装してみた
どうやって勉強しようかなと考えた時に[GroupiePlayGround][link1]を作り、exampleを見ながら興味があったものを実装することにしました。**4種類の活用例**を紹介したいと思います。
まずはこちらの技術も使っているのでご確認ください。

- DataBinding
- LiveData

### 共通の仕様
- Itemの削除が可能
- ClickとLongClickできるようになっている

### SimpleGroupie
ひたすらItemをadapterに追加したものです。
`Section`ごとにまとめて`HeaderItem`みたいなものを自作したらタイトル＋中身みたいなものを作れます。(マストでSectionでまとめる必要はないのかな...まとめる利点ってなにかあるのかな...)

#### POINTS
- `groupAdapter.add(Group)`のように追加する。
- `+=`という演算子もgroupieでは`add`として使えるようになっているので見た目としてもわかりやすいです。

<div align="center"> 
<img title='simple.jpg' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304276/b80b58b6-2e2b-e792-1b2e-fabf64edd632.gif' width="270" data-meta='{"width":590,"height":360}'>
</div>


### ExpandableGroupie
これは主に[ResoCoderさんの記事][link3]を参考にさせていただきました。それに加えてオリジナリティを出すためにアイテムにお気に入りか否かの属性を持たせてClickでアイテムを移動できるようにしました。`Section`の中身をExpandable(要素の表示をを広げたり縮めたり)できる。

#### POINTS

- `ExpandableGroup()`の引数には`ExpandableItem`というInterfaceを実装した`Item`を入れてあげる。
- `ExpandableGroup()`にExpandableにするアイテムを例の如く追加します。
- Itemクラス側でも`ExpandableGroup`を使って、ToggleListenerを設定したりとか、状態を管理しないといけない。

<div align="center"> 
<img title='expandable.jpg' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304276/7867e498-cb39-9238-978f-f98e9665c3b5.gif' width="270" data-meta='{"width":590,"height":360}'>
</div>


### CarouselGroupie
まるでカルーセルかのように横にスクロールできるもの。これもまたタイトル+カルーセルを一塊としてあげると綺麗なレイアウトになりそう。recyclerViewの中にrecyclerViewをネストするのは想像できたもののItemのコンストラクタにカルーセル用のadapterを渡す実装があるのかと驚きました。

#### POINTS
- `groupAdapter`に追加する`Item`の1つを`carouselItem`として`recyclerView`をもつlayoutを実装する。
- carousel内で表示させる`Item`なども含めた`carouselAdapter`を別で用意して、`carouselItem`のコンストラクタとして`carouselAdapter`を渡す。

<div align="center"> 
<img title='carousel.jpg' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304276/17a2fd0a-7bc6-d692-b445-8d6ac824ffa1.gif' width="270" data-meta='{"width":590,"height":360}'>
</div>

### DraggableGroupie
Itemを動かして順番を変えることができる楽しいUIができます。うまく動かないケースがあるのでそこをどうにかして修正したいところです...理解が不十分でごめんなさい。

#### POINTS
- 自分で作った`Item`を継承した`DraggableItem`を実装する。
- Itemクラスにて`ItemTouchHelper`というrecyclerViewにあるクラスを使って動作を取得する。
- `TouchCallBack`を使ってアイテムの順番を入れ替える処理をする。
- recyclerViewにCallBackをアタッチしてあげる。

<div align="center"> 
<img title='draggable.jpg' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304276/45c78886-19e8-af1c-e357-ac749f581006.gif' width="270" data-meta='{"width":590,"height":360}'>
</div>

## いろいろメモ
### Adapter#addAll と Adapter#update の違いって？
#### なんでそんなことを思ったのか
どちらも引数に`List<Group>`を取ります。
このようなケースがありました。もともと#addAllを使ってリストの中身の追加をしていて、のちに#updateで中身を変更したいとなって何も考えずにどちらも書いていました。
そうするとリストの中身の変更はされるものの、1回点滅してから表示が変更されるという挙動になってしまいました。
そこで#updateのみで実装したら、想定通りの挙動をしたので解決したのですが、#addAllとは...??となってしまいました。

#### 個人的見解
実装を見てみるとどちらも`adapter.addAll()`をしているということは変わりがないようです。
`update`は新しいGroupと古いGroupの差分を見て、よしなに処理をしてくれているようです。

### 綺麗にアニメーションされない！
うまくアニメーションが行われず、点滅してリストの中身が変わっているということがありました。`Item.getId()`を実装するとアニメーションが動くようです。


## まとめ
RecyclerViewを生で実装したときよりかなり分かりやすかったです。exampleを見ながらではありますが、今回勉強したことでレイアウトを作る幅がかなり広がったので嬉しいです。他にも無限にスクロールできたりとかスワイプでアイテムを削除できたりするものもあったので今後も参考にしたいと思います。今回はFragment上でほとんど全ての操作をしているので本当は他のクラスで実装するのが最適なのではないかなど思うことはたくさんあったので、よかったら是非ご指摘いただきたいです。読んでいただきありがとうございました。[今回作ったもの：GroupiePlayGround][link1]



[link1]:https://github.com/zoothezoo/GroupiePlayGround
[link2]:https://github.com/lisawray/groupie
[link3]:https://resocoder.com/2018/03/02/create-a-complex-recyclerview-quickly-with-groupie-library-android-kotlin-recyclerview-tutorial/#ExpandableHeaderItemkt!