a-5-1-2(3).Realm DBのデータ保存と更新、削除(配列以外、配列)
目標設定
Github
テスト実装
RealmTestActivity.kt
package com.example.androidtest
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.example.androidtest.databinding.ActivityRealmTestBinding
import io.realm.kotlin.ext.query
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlin.math.log
class RealmTestActivity : AppCompatActivity() {
private lateinit var binding: ActivityRealmTestBinding
@OptIn(DelicateCoroutinesApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRealmTestBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
val dogResult = RealmTestService.realm.query<Dog>(query = "dogId == $0", args = arrayOf(2))
.find()
var dogName = "いない"
if (dogResult.size > 0) {
dogName = dogResult.first().name
}
val personNum = RealmTestService.realm.query<Person>().find().size
Log.d("Realm情報", "抽出したDog名: $dogName 初期のPersonの数: $personNum")
logOfRealm()
// showMessage("抽出したDog名: $dogName 初期のPersonの数: $personNum")
binding.addPerson.stateListAnimator = null
binding.addPerson.setOnClickListener {
RealmTestService.realm.writeBlocking {
val personResult = this.query<Person>(
query = "personId == $0", args = arrayOf(2)).find()
if (personResult.size == 0) {
copyToRealm(Person().apply {
personId = 2
name = "追加した人"
age = 30
})
}
}
logOfRealm()
}
binding.updatePerson.stateListAnimator = null
binding.updatePerson.setOnClickListener {
RealmTestService.realm.writeBlocking {
val personResult = this.query<Person>(
query = "personId == $0", args = arrayOf(2)).find()
if (personResult.size > 0) {
personResult.first().name = "更新した人"
}
}
logOfRealm()
}
binding.deletePerson.stateListAnimator = null
binding.deletePerson.setOnClickListener {
RealmTestService.realm.writeBlocking {
val personResult = this.query<Person>(
query = "personId == $0", args = arrayOf(2)).find()
if (personResult.size > 0) {
delete(personResult.first())
}
}
logOfRealm()
}
binding.addPersonTask.stateListAnimator = null
binding.addPersonTask.setOnClickListener {
RealmTestService.realm.writeBlocking {
val personResult = this.query<Person>(
query = "personId == $0", args = arrayOf(1)).find()
var taskId = 0
if (personResult.first().tasks.size > 0) {
val maxTask = personResult.first().tasks.maxBy { it.taskId!! }
taskId = maxTask.taskId!! + 1
}
personResult.first().tasks.add(Task().apply {
this.taskId = taskId
name = "追加したタスク"
finished = false
})
}
logOfRealm()
}
binding.updatePersonTask.stateListAnimator = null
binding.updatePersonTask.setOnClickListener {
RealmTestService.realm.writeBlocking {
val personResult = this.query<Person>(
query = "personId == $0", args = arrayOf(1)).find()
if (personResult.size > 0 && personResult.first().tasks.size > 0) {
val minTask = personResult.first().tasks.minBy { it.taskId!! }
minTask.finished = true
}
}
logOfRealm()
}
binding.deletePersonTask.stateListAnimator = null
binding.deletePersonTask.setOnClickListener {
RealmTestService.realm.writeBlocking {
val personResult = query<Person>(
query = "personId == $0", args = arrayOf(1)).find()
if (personResult.size > 0) {
val tasks = personResult.first().tasks.filter { it.finished }
personResult.first().tasks.removeAll(tasks)
}
}
logOfRealm()
}
}
// private fun showMessage(message: String) {
// val builder = AlertDialog.Builder(this)
// builder.setTitle("Realmの検証")
// .setMessage(message)
// .setPositiveButton("OK") { _, _ ->
// }
// builder.create()
// builder.show()
// }
private fun logOfRealm() {
val parsonResult = RealmTestService.realm.query<Person>().find()
Log.d("Realm情報", "---Person---")
for (i in 0 ..< parsonResult.size) {
val parson = parsonResult[i]
Log.d("Realm情報",
"${parson.personId} ${parson.name} ${parson.age}")
if (parson.tasks.size > 0) {
Log.d("Realm情報", "---Person>Task---")
}
for (j in 0..<parson.tasks.size) {
val task = parson.tasks[j]
Log.d("Realm情報",
"${task.taskId} ${task.name} ${task.finished}")
}
}
Log.d("Realm情報", "---Dog---")
val dogResult = RealmTestService.realm.query<Dog>().find()
for(i in 0 ..< dogResult.size) {
val dog = dogResult[i]
Log.d("Realm情報",
"${dog.dogId} ${dog.name} ${dog.age}")
}
}
}
activity_realm_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp">
<TextView
android:id="@+id/text_1_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="0dp"
android:text="Realmの検証"
android:textSize="21sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<Space
android:layout_width="match_parent"
android:layout_height="4dp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="150dp"
>
<Button
android:id="@+id/add_person"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/style3_button_background"
app:backgroundTint="@null"
android:text="Personの追加(personId=2)"
android:padding="0dp"
android:layout_marginEnd="8dp"
android:textSize="11sp"
tools:ignore="HardcodedText"
style="?android:attr/buttonBarButtonStyle" />
<Button
android:id="@+id/update_person"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/style3_button_background"
app:backgroundTint="@null"
android:text="Personの更新(personId=2, 名前を変更する)"
android:padding="0dp"
android:layout_marginEnd="8dp"
android:textSize="11sp"
tools:ignore="HardcodedText"
style="?android:attr/buttonBarButtonStyle" />
<Button
android:id="@+id/delete_person"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/style3_button_background"
app:backgroundTint="@null"
android:text="Personの削除(personId=2)"
android:padding="0dp"
android:textSize="11sp"
tools:ignore="HardcodedText"
style="?android:attr/buttonBarButtonStyle" />
</LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="8dp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="150dp"
>
<Button
android:id="@+id/add_person_task"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/style3_button_background"
app:backgroundTint="@null"
android:text="Personのtaskの追加(personId=1, タスクIDを最大+1)"
android:padding="0dp"
android:layout_marginEnd="8dp"
android:textSize="11sp"
tools:ignore="HardcodedText"
style="?android:attr/buttonBarButtonStyle" />
<Button
android:id="@+id/update_person_task"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/style3_button_background"
app:backgroundTint="@null"
android:text="Personのtaskの更新(personId=1, タスクIDの最小のレコードをfinished=trueにする)"
android:padding="0dp"
android:layout_marginEnd="8dp"
android:textSize="11sp"
tools:ignore="HardcodedText"
style="?android:attr/buttonBarButtonStyle" />
<Button
android:id="@+id/delete_person_task"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/style3_button_background"
app:backgroundTint="@null"
android:text="Personのtaskの削除(personId=1 and finished=true)"
android:padding="0dp"
android:textSize="11sp"
tools:ignore="HardcodedText"
style="?android:attr/buttonBarButtonStyle" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
RealmTestService.kt
package com.example.androidtest
import android.util.Log
import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.EmbeddedRealmObject
import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
class Dog: RealmObject {
@PrimaryKey
var dogId: Int? = null
var name: String = ""
var age: Int = 0
}
class Person: RealmObject {
@PrimaryKey
var personId: Int? = null
var name: String = ""
var age: Int = 0
var tasks: RealmList<Task> = realmListOf()
}
class Task: EmbeddedRealmObject {
var taskId: Int? = null
var name: String = ""
var finished: Boolean = false
}
object RealmTestService {
private var localRealm: Realm? = null
val realm: Realm
get() {
if (localRealm != null) {
return localRealm!!
}
val config = RealmConfiguration.Builder(
schema = setOf(Dog::class, Person::class, Task::class))
// 64バイトのキーを動的に作成する必要あり
// キーの保存先も安全な場所に保存する必要あり
// .encryptionKey(Base64.decode("abc...", Base64.DEFAULT)) // 暗号化キー
.initialData {// DBの初期値
copyToRealm(Dog().apply {
dogId = 0
name = "いぬ"
age = 3
})
copyToRealm(Dog().apply {
dogId = 1
name = "うさぎ"
age = 2
})
copyToRealm(Dog().apply {
dogId = 2
name = "とり"
age = 2
})
copyToRealm(Person().apply {
personId = 0
name = "りょうたくん"
age = 20
})
copyToRealm(Person().apply {
personId = 1
name = "新たなりょうたくん"
age = 2
tasks = realmListOf(
Task().apply {
taskId = 0
name = "カレンダー作成"
finished = false
},
Task().apply {
taskId = 1
name = "アプリ申請"
finished = false
}
)
})
}.build()
localRealm = Realm.open(config)
Log.d("Realm情報", "開いたRealm ${localRealm!!.configuration.name}")
return localRealm!!
}
}