오늘은 안드로이드 ROOM에 대해 알아보도록 하겠습니다.
1. ROOM 이란?
- Room은 Jetpack에서 AAC(Android Architecture Components)로 제공하는 데이터베이스 라이브러리 입니다.
- Room을 사용하는 사례는 일상에서도 확인할 수 있습니다. 카카오톡이나 여러 SNS를 사용하다보면 네트워크가 연결되어 있지 않은데 채팅 내역 등을 확인 할 수 있는 경험 한번쯤 해보셧을꺼라 생각합니다. 이럴때 Room이나 다른 내부 DB를 사용하는것입니다!
2. ROOM의 구성요소
- Room Database
- 앱에 저장되어 있는 로컬 데이터에 대한 액세스 포인트를 제공해주는 역할을 합니다.
- DAO(Data Access Object)
- 데이터를 조작하는 쿼리 등을 작성해 놓은 클래스입니다. ex) insert,select,update,delete
- Entities
- 테이블을 정의해 놓은 클래스입니다.
이렇게 보면 이해가 안되실꺼 같아 예제를 보며 이해해보겠습니다.
간단하게 연락처를 저장하는 애플리케이션 예제를 보여드리도록 하겠습니다.
첫번째로 의존성 추가를 해야 합니다.
bulid.gradles.kts :app
plugins {
id 'kotlin-kapt'
}
dependencies {
implementation("androidx.room:room-runtime:2.4.3")
annotationProcessor("androidx.room:room-compiler:2.4.3")
kapt("androidx.room:room-compiler:2.4.3")
implementation("androidx.room:room-ktx:2.4.3")
}
다음으로 Entities 만들기부터 해보겠습니다.
Entities
import androidx.room.ColumnInfo
import androidx.room.Entity
@Entity(tableName = "PhoneBook")
data class PhoneBookEntities(
@PrimaryKey @ColumnInfo(name = "phoneNumber") val number : Int,
)
PhoneBook 이라는 테이블을 만들었고 컬럼은 number으로 설정 했습니다.
Room은 어노테이션을 사용하여 어떤 클래스인지 컴파일러에게 알려줘야 합니다.
Database
package com.example.practiceproject
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [PhoneBookEntities::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun getPhoneBookDAO() : PhoneBookDAO
companion object{
@Volatile
private var INSTANCE : AppDatabase? = null
private fun buildDatabase(context : Context): AppDatabase =
Room.databaseBuilder(context.applicationContext,AppDatabase::class.java,"phone-book").build()
fun getInstance(context: Context): AppDatabase =
INSTANCE ?: synchronized(this) {
INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
}
}
}
Database 클래스는 추상화 클래스로 작성해야 합니다.
마지막으로 DAO 클래스를 작성하고 사용하는 것을 보겠습니다.
Dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
@Dao
interface PhoneBookDAO {
@Query("SELECT * FROM phonebook")
fun getPhoneBook(): List<PhoneBookEntities>
@Insert
fun insertPhoneBook(phoneBook: PhoneBookEntities)
}
3개를 다 작성했으니 이제 추가, 불러오기를 해보겠습니다.
MainActivity
class MainActivity : AppCompatActivity() {
lateinit var addPhoneBookButton : Button
lateinit var recyclerView : RecyclerView
var arrayList = ArrayList<PhoneBookEntities>()
val adapter = PhoneBookAdapter(arrayList)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.recyclerview)
addPhoneBookButton = findViewById(R.id.button)
recyclerView.adapter =adapter
recyclerView.layoutManager = GridLayoutManager(this, 1)
selectPhoneNumber()
addPhoneBookButton.setOnClickListener {
dialogShow()
}
}
fun dialogShow(){
val dialog = AlertDialog.Builder(this)
dialog.setIcon(R.drawable.ic_launcher_foreground)
dialog.setTitle("전화번호 추가")
val numberEditText : EditText = EditText(this)
numberEditText.setHint("전화번호를 입력해주세요.")
dialog.setView(numberEditText)
// Dialog 에 확인, 취소 Button 추가
dialog.setPositiveButton("확인") { dialog, _ ->
var appDatabase: AppDatabase = AppDatabase.getInstance(this)
var phoneNumber:String = numberEditText.text.toString()
var phoneBookEntities = PhoneBookEntities(phoneNumber)
GlobalScope.launch {
withContext(Dispatchers.IO){
appDatabase.getPhoneBookDAO().insertPhoneBook(phoneBookEntities)
}
}
arrayList.add(phoneBookEntities)
adapter.notifyDataSetChanged()
dialog.dismiss()
}
dialog.setNegativeButton("취소"){ dialog,_ ->
dialog.dismiss()
}
dialog.show()
}
fun selectPhoneNumber(){
var appDatabase: AppDatabase = AppDatabase.getInstance(this)
GlobalScope.launch {
withContext(Dispatchers.IO){
for(i in appDatabase.getPhoneBookDAO().getPhoneBook()){
arrayList.add(i)
}
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="추가"
tools:layout_editor_absoluteX="244dp"
tools:layout_editor_absoluteY="550dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_margin="20dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
PhoneBookAdapter
class PhoneBookAdapter(val item : ArrayList<PhoneBookEntities>) : RecyclerView.Adapter<PhoneBookAdapter.ViewHolder>() {
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val phoneNumberTextView: TextView = itemView.findViewById(R.id.phoneNumber)
fun bind(item : PhoneBookEntities){
phoneNumberTextView.text = item.number.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return item.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(item.get(position))
}
item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
>
<TextView
android:id="@+id/phoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="전화번호"
android:textSize="20dp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
selectPhoneNumber 함수를 보면 appDatabase.getPhoneBookDAO().getPhoneBook() 함수를 호출해 저장된 전화번호를 불러오는 코드인것을 확인할 수 있습니다. room은 쿼리를 요청할때 메인 쓰레드에서 처리할 수 없기때문에 코루틴을 사용해 비동기 처리를 해주었습니다.
위 코드를 실행하면 아래 결과를 확인 할 수 있습니다.
이번 글에서는 room에 대해 알아보았습니다. room을 공부하는 분들에게 조금이나마 도움이 되었으면 좋겠습니다. 긴글 읽어 주셔서 감사합니다.
'Android' 카테고리의 다른 글
안드로이드 Compose란 + 예제 (0) | 2024.03.05 |
---|---|
안드로이드 DataBinding 사용 예제 (0) | 2024.03.04 |
Hilt 란? (0) | 2024.02.06 |
WebRTC 란? (2) | 2023.08.08 |
#1 안드로이드 4대 컴포넌트 (0) | 2023.04.29 |
댓글