AndroidのRecyclerViewをKotlinでかんたんに実装するライブラリ

# はじめに
この記事はAndroidでRecyclerViewを使おうとしたとき、かなり面倒で似たような処理が多かったので、まとめてしまおうと思ってライブラリを作った話です。
~~文章がめちゃくちゃですが気にしないでください~~

# 早く実装したい人へ
下のコードをまず追記します

```gradle:build.gradle(Project)
allprojects {
    repositories {
        // ↓これを追記
        maven { url 'https://jitpack.io' }
    }
}
```

```gradle:build.gradle(app)
dependencies {
    // ↓これを追記
        implementation 'com.github.peshogo:Android-Simple-RecyclerView:0.1.1'

}
```

これでGradleをSyncしてやればライブラリを使う準備が整います

使い方は：

```
(RecyclerView).initSimpleRecyclerView(
    コンテキスト(this)
    好みのデータ型のリスト,
    レイアウトのID
){ 好みのデータ型 ->
    データとレイアウトを結びつけるコード
}
```

使用例としては：
`rview`というIDをつけたRecyclerViewを`activity_main.xml`おいていたとします
また、リスト内のレイアウトのために`custom_row.xml`を用意して、中に`label`というIDのTextViewをおいていたとします

それをもとにかくと

```kotlin:MainActivity.kt
////// いろいろ
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val items = arrayListOf(
        "Some",
        "string",
        "array"
    )

    rview.initSimpleRecyclerView(this, items, R.layout.custom_row)
    { item ->
        label.text = item
    }
}
//////　いろいろ
```

多分これで動きます

こういうこともできます

```kotlin:MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)

    val items = arrayListOf(
            Video("Cool Video", "this is a cool video"),
            Video("hoge hoge", "foo bar foo bar")
    )

    rview.initSimpleRecyclerView(this, items, R.layout.custom_row) {
        title.text = it.title
        description.text = it.desctiption
    }
}

data class Video(val title: String, val desctiption: String)
```

# どういう仕組みか
## いままで
いままでRecyclerViewを使おうと思ったら

 - LayoutManagerの設定
 - Adapterの作成
 - ViewHolderの作成
 - 
をしなくてはいけませんでした
同じ型のViewを並べるだけならもっとかんたんにかけると思いまず普通に`String`の配列から作れるように作ってみました

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {

	override fun onCreate(savedInstanceState: Bundle?) {
	    super.onCreate(savedInstanceState)

	    setContentView(R.layout.activity_main)

	    val items = arrayListOf(
                "Some",
                "Text",
                "Array"
	    )
            
            // rview は Recyclerview
        rview.layoutManager = LinearLayoutManager(this)
        rview.adapter = SimpleAdapter(items)
    }

}

class SimpleAdapter(val items: List<String>): RecyclerView.Adapter<SimpleViewHolder>() {

	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleViewHolder {
		val row = LayoutInflater.from(parent.context).inflate(R.layout.custom_row,parent,false)
		return SimpleViewHolder(row)
	}

	override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
		holder.view.label.text = items[position]
	}

	override fun getItemCount(): Int {
		return items.size
	}

}

class SimpleViewHolder(val view: View): RecyclerView.ViewHolder(view)
```

これで動きます
でも、わかりづらい

## Bindingを外に出す
`SimpleAdapter`の`onBindViewHolder`を外側に出して好きにくっつけられるようにしました

また、そうするならViewも好きなのを入れられる方がいいので

```kotlin
class SimpleAdapter(val items: List<String>): RecyclerView.Adapter<SimpleViewHolder>() {
	/// いろいろ
	override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
		holder.view.custom_row_title.text = items[position]
    }
    /// いろいろ
}
```

これにバインディング用の関数`binder`を追加して

```kotlin
class SimpleAdapter(val items: List<String>,val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>() {
	/// いろいろ
	override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
		holder.view.binder(items[position])
	}
	/// いろいろ
}
```

こうしてViewのIDを自分で決められるようにして

```kotlin
class SimpleAdapter(val items: List<String>,val layout: Int, val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>() {

	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleViewHolder {
		val row = LayoutInflater.from(parent.context).inflate(layout, parent,false)
		return SimpleViewHolder(row)
	}
	
	override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
		holder.view.binder(items[position])
	}
	/// いろいろ
}
```

こうなる

これを使って実際に実装すると

```kotlin:MainActivity.kt
rview.layoutManager = LinearLayoutManager(this)
rview.adapter = com.shogo.mywayofmakingapps.SimpleAdapter(items,R.layout.custom_row){
	label.text = it
}
```

## String以外も使いたい
String でこれができるなら他の型でも行けるだろということで

```kotlin
class SimpleAdapter(val items: List<String>,val layout: Int, val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>()
```

これを

```kotlin
class SimpleAdapter<T>(val items: List<T>,val layout: Int, val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>()
```

こう変える

これでString以外も扱えるようになった。

## 1行で実装できるようにしたい
このままだと実装に２行必要なので１つの関数にまとめた

```kotlin
fun <T> RecyclerView.initSimpleRecyclerView(ctx: Activity, items: List<T>, layout: Int, binder: View.(T) -> Unit) {
    layoutManager = LinearLayoutManager(ctx)
    adapter = SimpleAdapter(items,layout,binder)
}
```

これでかんたんにRecyclerViewが実装できるようになった

# 改善していくところ
 * まだボタンを配置したときの挙動を考えられてないのでそれについて考えておきたい
 * Bindingの説明がわかりづらい

# まとめ
ただのリストを作るだけならこれで結構できるんじゃないでしょうか

# Github
これのレポジトリです
https://github.com/peshogo/Android-Simple-RecyclerView

説明で書いてあるコードはここです
https://github.com/peshogo/Android-Simple-RecyclerView/blob/master/simplerecyclerview/src/main/java/com/shogo/simplerecyclerview/SimpleRecyclerView.kt