클라이언트 내부 데이터베이스를 사용해서 여러 가지 기능들을 수행할 수 있습니다.
대표적으로 SharedPreference와 roomDB를 이야기할 수 있는데 이 중에서
안드로이드 제트팩의 구성요소이자 AAC 중에 하나인 room DB에 대해서 포스팅 해보겠습니다.
해당 관련 깃허브 주소입니다.
https://github.com/eukkbro/room
GitHub - eukkbro/room
Contribute to eukkbro/room development by creating an account on GitHub.
github.com
Room 이란?
공식문서에서는 다음과 같이 정의합니다.
데이터 베이스 프로그래밍을 이용하여 안드로이드 폰에서 데이터베이스를 관리하는 오픈소스 SQLite가 있는데,
Room 지속성 라이브러리는 SQLite를 완벽히 활용하면서 원활한 데이터베이스 액세스가 가능하도록 SQLite의 추상화 계층을 제공합니다.
https://developer.android.com/training/data-storage/room?hl=ko
Room을 사용하여 로컬 데이터베이스에 데이터 저장 | Android Developers
Room 라이브러리를 사용하여 더 쉽게 데이터를 유지하는 방법 알아보기
developer.android.com
공식문서에서도 SQLite API를 직접 사용하는 대신에 Room을 사용하는 것이 좋다고 얘기하고 있습니다.
구성요소
- 데이터베이스 클래스 : 데이터베이스를 보유하고 앱의 영구 데이터와의 기본 연결을 위한 기본 액세스 포인트 역할
- 데이터 항목 : 앱 데이터 베이스의 테이블
- 데이터 액세스 객체(DAO) : 앱이 데이터베이스의 데이터를 쿼리, 업데이트, 삽입, 삭제하는 데 사용할 수 있는 메서드 제공
구현
이전 포스팅에서 사용했던 리사이클러뷰와 함께 간단한 추가/삭제를 구현해 보겠습니다.
1. 의존성 추가
그래들의 모듈 수준에 의존성을 추가합니다.
dependencies {
def room_version = "2.6.1"
// Room
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
}
같은 글의 맨 위 plugins에 다음과 같은 줄도 추가해 줍니다.
kapt 관련해서 글을 따로 한번 적을 예정입니다!
plugins {
...
id 'kotlin-kapt'
}
2. 데이터 항목
변수들 각각이 우리가 흔히 알고 있는 데이터베이스의 행 하나를 나타냅니다.
@Entity
data class User(
@PrimaryKey val num: Int,
@ColumnInfo(name = "first_name") val first_name: String?,
@ColumnInfo(name = "second_name") val second_name: String?
)
3. 데이터 액세스 객체(DAO)
@Dao
interface UserDao{
@Query("SELECT * FROM user")
fun getAll() : List<User>
@Insert
fun insertAll(vararg users: User)
}
4. 데이터베이스
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
5. 메인 액티비티
뷰 바인딩을 사용한 예제입니다.
처음에 룸 DB 에 있는 데이터를 불러와서 리사이클러뷰에 띄워주고
버튼을 누르면 roomDB에 데이터를 추가해 주는 예제입니다.
룸은 메인스레드에서는 접근이 안되게 되어있습니다.
그래서 별개의 스레드를 사용해서 접근했습니다.
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
lateinit var adapter:MyAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
adapter= MyAdapter() //어댑터 객체 만듦
// Database 초기화
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "database-name"
).build()
// userDao 초기화
val userDao = db.userDao()
Thread { //room에 접근하기 위해 Thread 사용
var userList = userDao.getAll() as ArrayList<User>
Log.d("사이즈", "onCreate: ${userList.size}")
adapter.datalist = userList
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = adapter
}.start()
binding.buttonAdd.setOnClickListener {
Thread { //room에 접근하기 위해 Thread 사용
var addUser = User(adapter.itemCount,binding.editText1.text.toString(), binding.editText2.text.toString())
userDao.insertAll(addUser)
adapter.datalist.add(addUser)
Handler(Looper.getMainLooper()).post{
adapter.notifyDataSetChanged()
Toast.makeText(this,"성공적으로 추가했습니다",Toast.LENGTH_SHORT).show()
binding.editText1.setText("")
binding.editText2.setText("")
}
}.start()
}
}
}
6. 어댑터
class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
var datalist:ArrayList<User> = ArrayList()//리사이클러뷰에서 사용할 데이터 미리 정의
inner class MyViewHolder(private val binding: ItemViewBinding) : RecyclerView.ViewHolder(binding.root){
fun binding(user: User){
binding.textViewName1.text = user.first_name
binding.textViewName2.text = user.second_name
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
//레이아웃을 객체형태로 변환(inflate)하고 반환해준다.
val binding=ItemViewBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return MyViewHolder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.binding(datalist[position])
}
override fun getItemCount(): Int = datalist.size
}
7. 결과
추가도 잘 되고 불러오는 것도 잘 되는 것을 확인할 수 있습니다.
끝!
'안드로이드' 카테고리의 다른 글
[Android] 디자인 패턴 이해 (MVC/MVP/MVVM) (0) | 2024.04.30 |
---|---|
[Android] SharedPreferences, 간단한 정보 저장/불러오기 (0) | 2024.04.30 |
[SCRCPY] 안드로이드 기기 USB, WIFI를 통한 미러링 , 다중 미러링 (1) | 2024.04.03 |
[Android] 노란 경고 무시하지 말자 2 - Hardcoded string "텍스트", should use @string resource (0) | 2024.03.30 |
[Android] LinearLayout, 리니어 레이아웃 (0) | 2024.03.29 |