Android jetpack 소개에 이어
jetpack 에서 제공하는 Room 에 대해 알아보고,
기능을 활용해서 간단한 예제를 통해 정리하려고 합니다.
1. Room 소개
기존 안드로이드에서 제공하는 데이터베이스 SQLite 에서
오류에 대한 안정성과 원활하게 데이터베이스에 접근할 수 있는 jetpack 라이브러리입니다.
안드로이드 공식문서에서도 SQLite 보다 Room 사용을 적극적으로 권장하고있습니다.
2. Room 특징
Room에는 다음과 같은 세 가지 주요 구성요소가 있습니다.
▶ DataBase : 데이터베이스 홀더를 포함하며 앱의 지속적인 관계형 데이터의 기본 연결을 위한 기본 액세스 포인트 역할을 합니다.
▶ Entity : 데이터베이스 내의 테이블을 나타냅니다.
▶ Dao : 데이터베이스에 액세스하는 데 사용되는 메서드가 포함되어 있습니다.
앱은 Room 데이터베이스를 사용하여 데이터베이스와 연결된 데이터 액세스 개체 또는 DAO를 가져옵니다. 그런 다음 앱은 각 DAO를 사용하여 데이터베이스에서 항목을 가져오고 항목의 변경사항을 다시 데이터베이스에 저장합니다. 마지막으로 앱은 항목을 사용하여 데이터베이스 내의 테이블 열에 해당하는 값을 가져오고 설정합니다.
3. Room 활용
Room 을 활용하여 매일 할일(Todo)을 저장하는 예제를 살펴보겠습니다.
♣ Dependency
- ktx : kotlin 코드를 간결하게 작성할 수 있도록 추가
- recyclerview : ListView 상위버전으로 결과를 보여주기위해 추가
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
// constraintlayout
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
// ktx
implementation 'androidx.core:core-ktx:1.3.2'
// recycle view
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.recyclerview:recyclerview-selection:1.1.0-rc03"
// room
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"
testImplementation "androidx.room:room-testing:2.2.5"
}
♣ Entity
- id : 고유 아이디 필드 (자동으로 생성하도록 설정)
- title : 할일을 나타내주는 필드
- highPriority : 할일 중요도를 나타내주는 필드
@Entity
data class Todo(
val title: String,
val highPriority: Boolean
) {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
}
♣ Dao
DataBase 접근할 수 있는 메서드를 정의해줍니다.
@Dao
interface TodoDao {
@Query("SELECT * FROM todo")
fun getAll(): List<Todo>
@Query("SELECT * FROM todo WHERE title LIKE :title")
fun findByTitle(title: String): Todo
@Insert
fun insert(todo: Todo)
@Delete
fun delete(todo: Todo)
@Query("DELETE FROM todo")
fun deleteAll()
@Update
fun update(vararg todo: Todo)
@Query("UPDATE todo SET title = :title, isHighPriority = :isHighPriority WHERE id = :id")
fun update(id: Int, title: String, isHighPriority: Boolean): Int
}
♣ Database
Database 는 아래와같이 싱글톤으로 구현하였습니다.
@Database(entities = [Todo::class], version = 1)
abstract class TodoDataBase : RoomDatabase() {
abstract fun todoDao(): TodoDao?
companion object {
private val sLock = Any()
private var instance: TodoDataBase? = null
fun getInstance(context: Context): TodoDataBase? {
synchronized(sLock) {
if (instance == null) {
instance = Room.databaseBuilder(context,
TodoDataBase::class.java, "todo-db")
.allowMainThreadQueries() // FIXME : 일반적으로 mainThread 에서 사용하지 않음
.build()
}
return instance
}
}
}
}
♣ MainActivity
Room DataBase 를 생성해주고 Dao 메서드를 통해서 사용하는 것을 확인 할 수 있습니다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Room DataBase Load
val todoDataBase = TodoDataBase.getInstance(applicationContext)
// UI Initialize
val etTodo = findViewById<EditText>(R.id.etTodo)
val btnAdd = findViewById<Button>(R.id.btnAdd)
val rvResult = findViewById<RecyclerView>(R.id.rvResult)
val btnDeleteAll = findViewById<Button>(R.id.btnDeleteAll)
val btnDelete = findViewById<Button>(R.id.btnDelete)
val viewManager = LinearLayoutManager(this)
val todoList = todoDataBase?.todoDao()?.getAll()!!
val todoAdapter = TodoAdapter(ArrayList(todoList), todoDataBase)
rvResult.apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = todoAdapter
}
// UI Listener
btnAdd.setOnClickListener {
if (etTodo.text.toString().isNotEmpty()) {
val todo = Todo(etTodo.text.toString(), false)
todoDataBase.todoDao()?.insert(todo)
etTodo.setText("")
todoAdapter.addItem(todo)
}
}
btnDeleteAll.setOnClickListener {
todoDataBase.todoDao()?.deleteAll()
todoAdapter.deleteAllItem()
}
btnDelete.setOnClickListener {
val todo = todoAdapter.getSelectedItem()
todo?.run {
todoDataBase.todoDao()?.delete(this)
todoAdapter.deleteItem(this)
}
}
}
}
4. 결과
5. 예제 다운로드
참고자료
0 comments: