본문 바로가기
Android

안드로이드 ROOM 사용법 + 예제

by Taron 2024. 3. 3.

오늘은 안드로이드 ROOM에 대해 알아보도록 하겠습니다.

1. ROOM 이란?

  • Room은 Jetpack에서 AAC(Android Architecture Components)로 제공하는 데이터베이스 라이브러리 입니다. 
  • Room을 사용하는 사례는 일상에서도 확인할 수 있습니다. 카카오톡이나 여러 SNS를 사용하다보면 네트워크가 연결되어 있지 않은데 채팅 내역 등을 확인 할 수 있는 경험 한번쯤 해보셧을꺼라 생각합니다. 이럴때 Room이나 다른 내부 DB를 사용하는것입니다!

2. ROOM의 구성요소

  1. Room Database
    • 앱에 저장되어 있는 로컬 데이터에 대한 액세스 포인트를 제공해주는 역할을 합니다.
  2. DAO(Data Access Object)
    • 데이터를 조작하는 쿼리 등을 작성해 놓은 클래스입니다. ex) insert,select,update,delete
  3. 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

댓글