Room을 적용하여 대학교의 학생 목록을 관리하는 예시를 만들어보았다.
[구현 사항]
- db의 필요사항 - Primary key로 있을 id 값, 이름, 전공
- 삭제/추가 구현
- vararg 테스트를 위한 리스트 추가
- id 값은 자동으로 계산해서 추가(+1씩)
* viewBinding 사용, 코틀린으로 작성되었습니다.
enum class Major(val korName:String) {
ECONOMICS("경제학과"),
BIOLOGY("생물학과"),
LAWS("법학과"),
ACCOUNTING("회계학과"),
HISTORY("역사학과")
}
1. Entitiy
@Entity(tableName = "student")
data class Student(
var name : String? = null,
var major : String? = null
){
@PrimaryKey(autoGenerate = true) var id :Int? = null
}
목표가 autoIncreate가 되는 id 값이였기 때문에 autoGenerate를 true값으로 주고,
이 부분은 작성할 필요가 없어서 매서드 부분에서 제외시켰다.
2. DAO
@Dao
interface StudentDao {
@Insert
fun insertStudent(student: Student)
@Insert
fun insertAll(vararg student: Student)
@Delete
fun deleteStudent(student: Student)
@Query("SELECT * FROM student")
fun getAll() : List<Student>
}
학생 한 명을 넣을 수 있는 intsertStudio 와 여러 리스트를 넣기 위해 vararg를 사용한 insertAll을 만들었고, 목록을 가져오고 한 명씩 지울 수 있도록 추가했다.
3. RoomDatabase
@Database(entities = [Student::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun studentDao():StudentDao
companion object {
@Volatile
private var instance: AppDatabase? = null
fun getInstance(context: Context): AppDataase {
synchronized(this) {
var instance = instance
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"student.db"
)
.fallbackToDestructiveMigration()
.build()
this.instance = instance
}
return instance
}
}
}
}
4. 해당 Activity (RoomActivity)
class RoomActivity: AppCompatActivity() {
private lateinit var binding : ActivityRoomBinding
lateinit var db : AppDatabase
private var selectMajor : Major? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRoomBinding.inflate(layoutInflater)
setContentView(binding.root)
db = AppDatabase.getInstance(this)
setSpinner()
clickControl()
getList()
}
private fun setSpinner(){
val majorList = Major.values().toMutableList()
val majorNameList = mutableListOf<String>()
majorList.forEach {
majorNameList.add(it.korName)
}
val adapter = ArrayAdapter<String>(
this,android.R.layout.simple_spinner_dropdown_item,majorNameList
)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.majorSpinner.adapter = adapter
binding.majorSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
selectMajor = majorList[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
selectMajor = majorList[0]
}
private fun clickControl(){
binding.addBtn.setOnClickListener {
if(binding.nameText.text.isNullOrBlank()) return@setOnClickListener
addStudent()
}
binding.allAddButton.setOnClickListener {
addList()
}
}
private fun getList(){
Thread(Runnable{
runOnUiThread {
binding.listView.removeAllViews()
}
val inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
db.studentDao().getAll().forEach { student ->
runOnUiThread {
val studentView = ItemRoomBinding.inflate(inflater,binding.listView,false)
studentView.idTextView.text = student.id.toString()
studentView.nameTextView.text = student.name
studentView.majorTextView.text = student.major
studentView.deleteBtn.setOnClickListener {
Log.d("clickBtn","click deleteBtn")
deleteStudent(student)
}
binding.listView.addView(studentView.root)
}
}
}).start()
}
private fun addList(){
val list = mutableListOf<Student>()
list.apply {
add(Student("김나나",Major.ACCOUNTING.korName))
add(Student("이상엽",Major.BIOLOGY.korName))
add(Student("박하나",Major.ECONOMICS.korName))
add(Student("정이든",Major.HISTORY.korName))
add(Student("서율",Major.LAWS.korName))
add(Student("정재영",Major.HISTORY.korName))
add(Student("김철수",Major.ACCOUNTING.korName))
add(Student("박영희",Major.ECONOMICS.korName))
add(Student("조유나",Major.HISTORY.korName))
add(Student("박윤철",Major.LAWS.korName))
}
Thread(Runnable {
db.studentDao().insertAll(*list.toTypedArray())
getList()
}).start()
}
private fun addStudent(){
val name = binding.nameText.text.toString()
Thread(Runnable {
db.studentDao().insertStudent(Student(name,selectMajor!!.korName))
getList()
}).start()
}
private fun deleteStudent(student: Student){
Thread(Runnable {
db.studentDao().deleteStudent(student)
getList()
}).start()
}
}
- 전체 추가에는 임의의 리스트를 만들어서 insertAll을 사용해서 insert하도록 하였다
- 이름을 작성하는 란과, 만들어 놓았던 Major enum class를 통해 spinner로 선택하도록 해서 한 개씩 추가하도록 해놓았다.
[실제 실행된 화면]
전체추가를 2번 누른 상태로 id 값이 자동으로 들어가서 값이 다르기 때문에 나머지 값이 같아도 잘 들어갔다.
[시행 착오]
- 초반에 Entity에 enum class인 Major을 넣어다가 당연히 값이 제대로 오지 않았고 korName값을 이용해서 넣기에 오류도 안나고 꺼내도 바로 리스트에 보이도록 하였다.
좀 더 발전하면 Major table을 만들어서 Primary 값을 통해 가져오면 될 것 같다.
- Entity Cannot find setter for field 에러
@Entity
data class Student(
@PrimarKey val id :Int,
val name : String,
val major : String
)
처음에 위와 같이 작성을 했다가 Cannot find setter for field 에러가 발생했다.
검색을 해보니 기본 설정값을 넣어줘야 한다고 해서 넣었더니 오류가 없어졌다.
@Entity(tableName = "student")
data class Student(
@PrimaryKey var id :Int? = null,
var name : String? = null,
var major : String? = null
)
차후는 필요에 의해 상단의 최종 버전으로 발전되었다!
'개발 공부 > 안드로이드' 카테고리의 다른 글
recyclerview 더 효율적으로 사용하기 - ListAdapter와 DiffUtil (0) | 2022.07.03 |
---|---|
android contextMenu - 선택지 띄우기, recyclerview (0) | 2022.07.03 |
android Room 1 - 알아보기 (0) | 2022.07.03 |
안드로이드 onNewIntent 관련 알아보기, lauchMode (0) | 2022.07.03 |
android, kotlin 시간차이 구하기 (0) | 2022.07.03 |