KotlinでRealm（他のDBとの概要比較）

kotlinで初めてRealm使ったの行ったことをまとめときます。
初学者の参考になれば


#Realmとは
iosやAndroidの端末内で動くデータベースです。


#データベース比較(RealmとRoom)
Androidでよく使われるRealmとRoomの簡単な比較をまとめ。
使い分け大事です。

##Realm
**メリット**
・速い
動作はSQLiteよりも早く、
・iosとAndroidともに対応

**デメリット**
apkファイルを2.5MB増加させる

##Room
**メリット**
・SQLiteデータベースにアクセスする処理がとても簡単に記述できます。
・SQLの中に現れるカラム名のミスなどがコンパイル時にエラーとして検出できることが強みです。
・LiveDataと一緒に使えばデータ変更を検知してUIを更新するような処理がとても簡単に記述できます。

**デメリット**
Swiftにはない


#今回作るアプリ
テキストを入力してボタンを押すとひたすらにRealmに保存されていき、表示するアプリになります。
データの読み込み、追加を学べます。

#Gradleの設定

今回Recyclerviewを使うのでそれも追加します。

```app/build.gradle

apply plugin: "realm-android"
//省略
dependencies {
    //省略
    //Realm
    implementation 'io.realm:android-adapters:3.1.0'

    //recyclerview
    implementation 'androidx.recyclerview:recyclerview:1.1.0'

}
```

#Realmの初期設定
Applicationクラスを作ります。
アプリを起動した際に最初に動くクラスになります。
何も考えなくていい初期化をします。
Realmの設定をいじることができます。

```Application.kt
class Application: Application() {

    override fun onCreate() {
        super.onCreate()

        //Realmの初期化
        Realm.init(this)
        val config = RealmConfiguration.Builder()
            //もともとあったデータを全て削除してくれる（なくても問題ない）
            .deleteRealmIfMigrationNeeded()
            .build()
        Realm.setDefaultConfiguration(config)
    }

}
```

```AndroidManifest.xml
<application
        //追加
        android:name=".Application"
       //省略
        >
    </application>
```


#Modelの作成

ＤＢのモデルを設定する。
アノテーションについては**PrimaryKey**を設定しないと値の変更ができなくなります
また、クラスを**open**属性にしないと継承、オーバーライドできないので注意。
Realmで作るときの注意点として、RealmObjectを継承する必要があります。

```Model.kt
open class Model : RealmObject() {
    @PrimaryKey
    var id: String = UUID.randomUUID().toString()
    var title: String = ""
}
```

#Adapterの設定
ここで普段のRecyclerViewとは違いRealmならではの部分があります。

はじめにクラスの継承について`RecyclerViewAdapter`を使っているとこがRealmを使うと`RealmRecyclerViewAdapter`になります。
その際に`ViewHolder`だけを指定するのではなく、`Model`も指定します。

クラスの引数に関しては、あまり理解出来なかったです。他の記事等みなさんこのような形で書かれていたので、深い理解が出来ませんでした。

```Adapter.kt
class Adapter(
    private val context: Context,
    private val List: OrderedRealmCollection<Model>?,
    private val autoUpdate: Boolean
) : RealmRecyclerViewAdapter<Model, Adapter.ViewHolder>(List, autoUpdate) {

```

次にクラスの中身です。
ここはRecyclerViewの時と変わりありません。

```Adapter.kt
    //リストの取得件数
    override fun getItemCount(): Int {
        return List?.size ?: 0
    }
    override fun onCreateViewHolder(viewGroup: ViewGroup, position: Int): ViewHolder {
        val view: View = LayoutInflater.from(context).inflate(R.layout.item, viewGroup, false)

    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val person = List?.get(position)
        holder.textView.text = person?.title
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.textView
    }
```
最終的な形です。

```Adapter.kt
class Adapter(
    private val context: Context,
    private val List: OrderedRealmCollection<Model>?,
    private val autoUpdate: Boolean
) : RealmRecyclerViewAdapter<Model, Adapter.ViewHolder>(List, autoUpdate) {

    override fun getItemCount(): Int {
        return List?.size ?: 0
    }

    override fun onCreateViewHolder(viewGroup: ViewGroup, position: Int): ViewHolder {
        val view: View = LayoutInflater.from(context).inflate(R.layout.item, viewGroup, false)

    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val person = List?.get(position)
        holder.textView.text = person?.title
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.textView
    }
}
```

#Activityにセット

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

    private val mRealm: Realm by lazy {
        Realm.getDefaultInstance()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val read = readList()

        //btnAddというiDのついたボタンを押した時の処理
        btnAdd.setOnClickListener {
            addList(editText.text.toString())
            //加えた後にreadしないと追加されても表示されないので読み込み処理も書きます。
            read
        }

        //RecyclerViewのAdapter、layouｔなどの設定
        val adapter = Adapter(this, read, true)
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter
    }

    //Realmにあるデータを読み込みます。
    fun readList(): RealmResults<Model> {
        return mRealm.where(Model::class.java).findAll()
    }

    //Realmにデータを追加します。
    fun addList(title:String){
        mRealm.executeTransaction {
            var model = mRealm.createObject(Model::class.java , UUID.randomUUID().toString())
            model.title = title
            mRealm.copyToRealm(model)
        }
    }

}
```
`mRealm`の変数ですが`lazy`という委譲プロパティを使って遅延初期化をしています。
これはこの変数が最初に参照されたときに{}内の値をsetして初期化します。

#スクショ
![Screenshot_20191208_131304_com.example.realmapp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188385/d314a94c-6870-2e74-c47a-fc80d4b02ae4.jpeg)


#終わりに
CardViewとDataBindingを付け加えたい（間に合わなかった。）


#参考
DBの比較一覧
https://github.com/AlexeyZatsepin/Android-ORM-benchmark
Kotlin+Realm+RecyclerViewを使ってTodoアプリを作る
https://qiita.com/konatsu_p/items/5ab92ebce46c9479876b
KotlinでRealmとRecyclerViewを組み合わせて使ってみる
https://qiita.com/keseran/items/07b01b2dd22a0addd1a3