iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
1
Mobile Development

程式初學:Android與Kotlin系列 第 6

Day 6--Room(二) 實作,爲app建立一個資料庫,新增資料存入

  • 分享至 

  • xImage
  •  

Room(二) 實作,爲app建立一個資料庫,新增資料存入

設定觀察環境

先建立一個環境可觀察database是否有正確寫入資料
https://github.com/facebook/stetho 找到Download(如圖)

產生一個ExtApplication class

import android.app.Application
import com.facebook.stetho.Stetho

class ExtApplication : Application(){
    override fun onCreate() {
        super.onCreate()
        Stetho.initializeWithDefaults(this);
    }
}

設定資料庫

拿來練習的範例是聯絡人資料,包含姓名;電話;地址
我們現在要加入資料庫,讓資料輸入後可存在手機

Entity

把data class加入需要的註解,變成Entity (Person.kt)

@Entity(tableName = "person_table")
data class Person(
    @ColumnInfo(name = "person_name")
    val name: String,

    @ColumnInfo(name = "person_phone")
    val phone: String,

    @ColumnInfo(name = "person_address")
    val address: String,

    @PrimaryKey(autoGenerate = true)
    var personId: Long = 0L
)

Dao

建立要操作資料庫的interface (PersonDataDao.kt)

@Dao
interface PersonDataDao {
    @Insert
    fun insert(person: Person)

    @Update
    fun update(person: Person)

    @Query("SELECT * FROM person_table WHERE person_phone = :key")
    fun get(key: Int): Person?

    @Query("DELETE FROM person_table")
    fun clear()

    @Query("SELECT * FROM person_table ORDER BY personId DESC")
    fun getAll(): List<Person>
}

Database

建立database (PersonDatabase.kt)

@Database(entities = [Person::class], version = 1, exportSchema = false)
abstract class PersonDatabase : RoomDatabase() {

    abstract val personDataDao: PersonDataDao

    companion object {

        @Volatile
        private var INSTANCE: PersonDatabase? = null

        fun getInstance(context: Context): PersonDatabase {
            synchronized(this) {
                var instance = INSTANCE

                if (instance == null) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        PersonDatabase::class.java,
                        "person_database"
                    )
                        .fallbackToDestructiveMigration()
                        .build()

                    INSTANCE = instance
                }
                return instance
            }
        }
    }
}

執行app後,看到報錯

Cannot access database on the main thread since it may potentially lock the UI for a long period of time

原來建立資料庫不能使用主執行緒,須要在後台執行,但目前還沒了解要如何用
所以先呼叫.allowMainThreadQueries()使資料庫可在主執行緒中執行
修改爲

@Database(entities = [Person::class], version = 1, exportSchema = false)
abstract class PersonDatabase : RoomDatabase() {

    abstract val personDataDao: PersonDataDao

    companion object {

        @Volatile
        private var INSTANCE: PersonDatabase? = null

        fun getInstance(context: Context): PersonDatabase {
            synchronized(this) {
                var instance = INSTANCE

                if (instance == null) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        PersonDatabase::class.java,
                        "person_database"
                    )
                        .allowMainThreadQueries()   //通常不建議在主執行緒中這樣做
                        .fallbackToDestructiveMigration()
                        .build()

                    INSTANCE = instance
                }
                return instance
            }
        }
    }
}

使用觀察環境檢查資料庫是否已正確建立

implementation 'com.facebook.stetho:stetho:1.5.1'放入gradle:app的dependencies
run app後,使用chrome開啓chrome://inspect/#devices
會看到target與專案名稱,點選inspect
會出現DevTools視窗,可以看到資料庫person_database

執行建立資料庫

準備在MainActivity中初始化資料庫

先在class MainActivity{}中宣告
private lateinit var db: PersonDatabase

然後在onCreate()中取得初始化
db = PersonDatabase.getInstance(this)

之後就可以呼叫DAO中的方法來操作資料庫,例如db.personDataDao.insert()
不過使用時注意須將符合的物件作爲引數傳入

新增資料

那麼就做一個button,依照Entity屬性,新增一筆資料進入資料庫

confirmButton.setOnClickListener {
            val item = Person(
                dialogItem.ed_name.text.toString(),
                dialogItem.ed_phone.text.toString(),
                dialogItem.ed_address.text.toString()
            )
            if (dialogItem.ed_name.text.isNotEmpty() && dialogItem.ed_phone.text.isNotEmpty()) {
                db.personDataDao.insert(item)
                notifyAdapter()
                dialog.dismiss()
            } else {
                Toast.makeText(this, "請輸入姓名,電話", Toast.LENGTH_SHORT).show()
            }

            dialogItem.ed_name.text.clear()
            dialogItem.ed_phone.text.clear()
            dialogItem.ed_address.text.clear()
        }

打開DevTools,可以看到資料有寫進去了


上一篇
Day 5--Room(一) 簡介
下一篇
Day 7--retrofit 簡介
系列文
程式初學:Android與Kotlin30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言