์๋ ํ์ธ์ ๐
์ค๋์ ์๋๋ก์ด๋ Room์ ์ฌ์ฉ๋ฒ์ ๋ํด์ ํฌ์คํ ํด๋ณด๋ ค ํฉ๋๋ค.

Room์ด๋?
์ค๋งํธํฐ ๋ด์ฅ DB์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก
ORM(Object Relational Mapping)๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
Room์ DB ๋ฐ์ดํฐ๋ฅผ Java ๋๋ ์ฝํ๋ฆฐ ๊ฐ์ฒด๋ก ๋งคํํด์ฃผ๋ฉฐ,
SQLite๋ฅผ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํจ์ผ๋ก์จ DB๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ๋ถ๋ฆฌํ๊ณ
๋ฐ์ดํฐ ์ ๊ทผ์ ํธ์์ฑ์ ๋์ฌ์ฃผ์ด ์ ์ง๋ณด์๋ฅผ ํธ๋ฆฌํ๊ฒ ํด ์ค๋๋ค.
Room์ ๊ตฌ์กฐ์ ๋ํด์
room์ ๊ตฌ์กฐ๋ ํฌ๊ฒ
Database , DAO , Entity๋ก ๋๋ ์ ์์ต๋๋ค.
์๋๋ Room์ ๊ตฌ์กฐ์ด๋ฉฐ ๊ฐ๊ฐ์ ๋ํด ์ค๋ช ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
Entity(์ํฐํฐ)
DB ๋ด์ Table๋ก class์ ๋ณ์๋ค์ด ์นผ๋ผ(column)์ด ๋์ด Table์ด ์์ฑ๋ฉ๋๋ค.
Annotation | ์ค๋ช | ์ฌ์ฉ๋ฒ |
@Entity | Table ์ด๋ฆ์ ์ ์ธํฉ๋๋ค. | @Entity(tableName = StudentEntry.TABLE_NAME) |
@PrimaryKey | ํด๋น property๋ฅผ primaryKey๋ก ์ง์ ํฉ๋๋ค. | |
@ColumnInfo | Table ๋ด column ์ ๋ณ์์ ๋งค์นญ ์์ผ์ค๋๋ค. |
DAO(Data Access Object)
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ์ฌ ์ํํ ์์ ์ ๋ฉ์๋ ํํ๋ก ์ ์ํ๋ class์ ๋๋ค.(SQL ์ฟผ๋ฆฌ๋ ์ง์ ๊ฐ๋ฅ)
Annotation | ์ค๋ช |
@Insert | Entity๋ฅผ setํ๋ ํจ์ ๋๋ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค. @Entity๋ก ์ ์๋ class๋ง ์ธ์๋ก ๋ฐ๊ฑฐ๋, ๊ทธ class์ collection ๋๋ array ๋ง ์ธ์๋ก ๋ฐ์ ์ ์์ต๋๋ค. |
@Update | Entity๋ฅผ updateํ๋ ํจ์ ๋๋ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค. |
@Delete | Entity๋ฅผ deleteํ๋ ํจ์ ๋๋ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค. |
@Query | ์ ์ธ๋ query๋ฅผ ํตํด DB๋ฅผ ์กฐํํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ ํจ์ ๋๋ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค. |
DataBase
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฒด์ ์ธ ์์ ์ ์ญํ ์ ํ๋ ์ถ์ ํด๋์ค๋ก
RoomDB์์ DAO๋ฅผ ๊ฐ์ ธ์์ ๊ฐ์ฒด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ CRUD ์ฒ๋ฆฌํฉ๋๋ค.
์์ฑ | ์ค๋ช |
entities | Database์ ์ด๋ค Entitiy๊ฐ ์๋์ง ๋ช ์ |
version | Database์ version์ ๋ํ๋ธ๋ค (scheme์ด ๋ฐ๋๋ ํจ๊ป ๋ฐ๊พธ์ด ์ฃผ์ด์ผํ๋ค.) |
scheme | Room์ Schema ๊ตฌ์กฐ๋ฅผ ํด๋๋ก Export ํ ์ ์๋์ง์ ๋ํ ์ฌ๋ถ๋ฅผ ์ค์ |
์ด์ ๋ ์์ ๋ฅผ ํตํด ์ฌ์ฉ๋ฒ์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ๐ค
๋จผ์ , ์ ๋ฐ์ ์ธ RoomDB ์ค์ ๋ถํฐ ๊ด๋ จ class๋ค์ ๋ง๋ค๊ฒ ์ต๋๋ค.
1. gradle์ ์ค์ ํด์ค๋๋ค.
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt' // kapt๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ํ์ ์ถ๊ฐ
}
android{
... ์๋ต
buildFeatures {
viewBinding true
dataBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
//Room
implementation 'androidx.room:room-runtime:2.4.3'
implementation "androidx.room:room-ktx:2.4.3"
kapt 'androidx.room:room-compiler:2.4.3'
// Coroutine
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
}
ํ์๋ ํด๋น ์์ ์์ Coroutine๊ณผ DataBinding์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํด๋น ๋ถ๋ถ๋ ํจ๊ป ์ถ๊ฐํด์ฃผ์์ต๋๋ค. ๐
2. Entity๋ฅผ ์์ฑํด์ค๋๋ค.
@Entity(tableName = "user_tbl")
data class UserEntity(
@PrimaryKey(autoGenerate = true)
val userId: Int?,
var userName: String,
var userAge: Int
)
3. DB๋ฅผ ์ปจํธ๋กคํ DAO interface๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
@Dao
interface UserDao {
@Insert // ์๋ก์ด User ์์ฑ
suspend fun insertUser(user : UserEntity)
@Query("SELECT * FROM user_tbl") // ๋ชจ๋ User ๊ฐ์ ธ์ค๊ธฐ
suspend fun getAllUser() : MutableList<User>
@Delete // ์ ํํ User ์ญ์ ํ๊ธฐ
suspend fun deleteUser(user : UserEntity)
@Update // ์ ํํ User ์
๋ฐ์ดํธ ํ๊ธฐ
suspend fun updateUser(user : UserEntity)
}
/**
* User์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ๋ ์ฌ์ฉํ data class
**/
data class User (
val userId : Int ,
var userName : String ,
var userAge : Int
) : Serializable
4. Application class๋ฅผ ์์ฑํ์ฌ Application Context๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋๋ก ํฉ๋๋ค.
class MainApplication : Application() {
companion object{
private lateinit var appInstance : MainApplication
fun getInstance() = appInstance
}
override fun onCreate() {
super.onCreate()
appInstance = this
}
}
5. RoomDB๋ฅผ ์์ฑํด์ค๋๋ค.
@Database(entities = [UserEntity::class] , version = 1 , exportSchema = false)
abstract class UserDatabase : RoomDatabase() {
abstract fun userDAO() : UserDao
companion object{
private lateinit var instance : UserDatabase
internal fun getInstance() : UserDatabase {
if(!::instance.isInitialized){
synchronized(UserDatabase::class.java){
instance = Room.databaseBuilder(
MainApplication.getInstance() ,
// Application Context๋ฅผ ์ฐธ์กฐํ์ฌ ์ฑ๊ณผ ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ฐ๊ฒ ํด์ค๋๋ค.
// ์ฆ, ํด๋น ์ฑ์ด ์ฃฝ์ผ๋ฉด instance๋ ์ฌ๋ผ์ง
UserDatabase::class.java ,
"user.db" ,
).build()
}
}
return instance
}
}
}
โ๏ธ Database๋ฅผ ์์ฑํ๋ ์ผ์ ๊ต์ฅํ ๋ง์ IO๊ฐ ๋ฐ์ํ๋ ์ผ์ด๋ฏ๋ก ์ฑ๊ธํด ํจํด์ ํตํด ๋จ ํ ๋ฒ๋ง ์์ฑํ๋๋ก ํฉ๋๋ค.
์ด๋ฒ์๋ MVVMํจํด์ ํตํด Room์ ์ฌ์ฉํ๋ ์ ๋ฐ์ ์ธ ์ฝ๋์ ๋ํด
์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค.
1. MainActivity( ์ ๋ ฅ์ฐฝ )
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="activityMainViewModel"
type="com.lee.viewmodel.ActivityMainViewModel" />
</data>
<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">
<LinearLayout
android:id="@+id/userNameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="10dp"
app:layout_constraintTop_toTopOf="parent"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="์ด๋ฆ"
android:textSize="20sp"
android:layout_marginStart="10dp"
/>
<EditText
android:id="@+id/userNameEditText"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="20dp"
android:background="@drawable/border_textview"
android:text="@={activityMainViewModel.userName}"
android:paddingStart="10dp"
android:paddingEnd="0dp"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/userAgeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/userNameLayout"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="๋์ด"
android:textSize="20sp"
android:layout_marginStart="10dp"
/>
<EditText
android:id="@+id/userAgeEditText"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="20dp"
android:background="@drawable/border_textview"
android:text="@={activityMainViewModel.userAge}"
android:inputType="number"
android:paddingStart="10dp"
android:paddingEnd="0dp"
/>
</LinearLayout>
<Button
android:id="@+id/confirmButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="์ ์ฅํ๊ธฐ"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_margin="10dp"
android:onClick="@{() -> activityMainViewModel.insertUser()}"
/>
<Button
android:id="@+id/listButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/confirmButton"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="๋ชฉ๋ก์ผ๋ก"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
private lateinit var mViewModel : ActivityMainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this , R.layout.activity_main)
mViewModel = ViewModelProvider(this@MainActivity , MainViewModelFactory(MainRepository.getInstance()))[ActivityMainViewModel::class.java]
binding.activityMainViewModel = mViewModel
addListeners()
observeData()
}
private fun addListeners() { // ๋ฆฌ์ค๋ ์ถ๊ฐ
with(binding){
listButton.setOnClickListener {
with(Intent(this@MainActivity , ListActivity::class.java)){
startActivity(this)
}
}
}
}
private fun observeData() { // LiveData ๊ด์ฐฐ ํจ์
with(mViewModel){
message.observe(this@MainActivity){
Toast.makeText(MainApplication.getInstance() , it , Toast.LENGTH_SHORT).show()
}
}
}
}
1-1. MainActivity( ์ ๋ ฅ์ฐฝ )์ ViewModel
class ActivityMainViewModel(private val repository: MainRepository) : ViewModel() {
val userName = MutableLiveData<String>("")
val userAge = MutableLiveData<String>("")
val message = MutableLiveData<String>()
fun insertUser(){ // Repository๋ฅผ ํตํด userDAO์ insertUser๋ฅผ ํธ์ถํ๋ค.
CoroutineScope(Dispatchers.IO).launch {
val user = UserEntity(null , userName.value!! , userAge.value!!.toInt())
repository.insertUser(user)
CoroutineScope(Dispatchers.Main).launch {
message.value = "์ ์์ ์ผ๋ก ๋ฑ๋ก๋์์ต๋๋ค."
}
}
}
fun updateUser(user : UserEntity){ // Repository๋ฅผ ํตํด userDAO์ updateUser๋ฅผ ํธ์ถํ๋ค.
CoroutineScope(Dispatchers.IO).launch {
with(user){
val updateUser = UserEntity(userId , userName , userAge)
repository.updateUser(updateUser)
CoroutineScope(Dispatchers.Main).launch{
message.value = "์ ์์ ์ผ๋ก ์
๋ฐ์ดํธ ๋์์ต๋๋ค."
}
}
}
}
}
์ ViewModel์ MainActivity์ UpdateActivity์์ ํจ๊ป ์ฌ์ฉํ ViewModel์ ๋๋ค.
1-2. ViewModel Factory
class MainViewModelFactory(private val repository: MainRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return if(modelClass.isAssignableFrom(ActivityMainViewModel::class.java)){
ActivityMainViewModel(repository) as T
}else if(modelClass.isAssignableFrom(ActivityListViewModel::class.java)){
ActivityListViewModel(repository) as T
} else {
throw java.lang.IllegalArgumentException("ํด๋น ViewModel์ ์ฐพ์์ ์์ต๋๋ค!")
}
}
}
1-3. Repository class
class MainRepository {
private val userDao = UserDatabase.getInstance().userDAO()
companion object{ // Repository๋ ์ฑ๊ธํด ํจํด์ผ๋ก instance๋ฅผ ๊ฐ์ ธ์ฌ๊ฒ์ด๋ค.
private lateinit var instance : MainRepository
fun getInstance() : MainRepository {
if(!::instance.isInitialized){
instance = MainRepository()
}
return instance
}
}
suspend fun insertUser(user : UserEntity) = userDao.insertUser(user)
suspend fun deleteUser(user : UserEntity) = userDao.deleteUser(user)
suspend fun updateUser(user : UserEntity) = userDao.updateUser(user)
suspend fun getAllUser() = userDao.getAllUser()
}
2. ListActivity(User ๋ชฉ๋ก ์กฐํ ํ์ด์ง)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/headerTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:gravity="center"
android:text="์ ์ ๋ชฉ๋ก"
android:textSize="30sp"
android:padding="5dp"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/userListRecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/headerTitle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:listitem="@layout/user_list_item"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
private const val TAG = "ListActivity"
const val EXTRA_SELECTED_USER = "selected_user" // ์ ํ๋ User ๊ฐ์ฒด๋ฅผ Intent์ ๋ณด๋ผ๋ ์ฌ์ฉํ๋ key
class ListActivity : AppCompatActivity() {
private lateinit var binding : ActivityListBinding
private lateinit var mRecyclerViewAdapter: UserListRecyclerViewAdapter
private lateinit var mViewModel : ActivityListViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityListBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
mViewModel = ViewModelProvider(this@ListActivity , MainViewModelFactory(MainRepository.getInstance()))[ActivityListViewModel::class.java]
observeData()
initRecyclerView()
}
override fun onResume() {
super.onResume()
mViewModel.getAllUser()
}
/**
* RecyclerView ์ด๊ธฐํ
**/
private fun initRecyclerView() {
mRecyclerViewAdapter = UserListRecyclerViewAdapter()
mRecyclerViewAdapter.setOnMenuItemClickListener(PopupMenuClickListener())
mRecyclerViewAdapter.setOnItemClickListener(UserItemClickListener())
with(binding.userListRecyclerView){
layoutManager = LinearLayoutManager(this@ListActivity)
adapter = mRecyclerViewAdapter
}
}
@SuppressLint("NotifyDataSetChanged")
private fun observeData() {
with(mViewModel){
userList.observe(this@ListActivity){
mRecyclerViewAdapter.setList(it)
mRecyclerViewAdapter.notifyDataSetChanged()
}
message.observe(this@ListActivity){
Toast.makeText(MainApplication.getInstance() , it , Toast.LENGTH_SHORT).show()
}
}
}
/**
* PopupMenu ์ ํ์ ๋ฐ์ํ๋ Listener
**/
private inner class PopupMenuClickListener() : OnMenuItemClickListener{
override fun onMenuItemClick(menuItem: MenuItem?): Boolean {
when(menuItem?.itemId){
R.id.delete -> {
Log.d(TAG, "onMenuItemClick: click delete")
val deleteUser : UserEntity
with(mRecyclerViewAdapter.getSelectedUser()){
deleteUser = UserEntity(userId , userName , userAge)
}
mViewModel.deleteSelectedUser(deleteUser)
}
}
return true
}
}
/**
* RecyclerView Item ์ ํ์ ๋ฐ์ํ๋ Listener
**/
private inner class UserItemClickListener : UserListRecyclerViewAdapter.OnItemClickListener{
override fun onItemClick(view: View, data: User, position: Int) {
with(Intent(this@ListActivity , UpdateActivity::class.java)){
putExtra(EXTRA_SELECTED_USER , data)
startActivity(this)
}
}
}
}
2-1. ListActivity์ ViewModel
class ActivityListViewModel(private val repository: MainRepository) : ViewModel() {
val userList = MutableLiveData<MutableList<User>>()
val message = MutableLiveData<String>()
fun getAllUser(){ // ๋ชจ๋ User ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
CoroutineScope(Dispatchers.IO).launch {
val list = repository.getAllUser()
CoroutineScope(Dispatchers.Main).launch {
userList.value = list
}
}
}
fun deleteSelectedUser(user : UserEntity){ // ์ ํ๋ User ์ญ์ ํ๊ธฐ
CoroutineScope(Dispatchers.IO).launch {
repository.deleteUser(user)
getAllUser()
CoroutineScope(Dispatchers.Main).launch{
message.value = "์ ์์ ์ผ๋ก ์ญ์ ๋์์ต๋๋ค."
}
}
}
}
2-2. RecyclerView๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ Adapter class
class UserListRecyclerViewAdapter : RecyclerView.Adapter<UserListRecyclerViewAdapter.UserListRecyclerViewHolder>() {
private var userList = mutableListOf<User>()
private var mOnMenuItemClickListener : OnMenuItemClickListener? = null
private var mOnItemClickListener : OnItemClickListener? = null
private lateinit var mSelectedData : User
/**
* ItemClickListener๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด Interface๋ฅผ ์ ์ธ
**/
interface OnItemClickListener {
fun onItemClick(view : View, data : User , position: Int)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserListRecyclerViewHolder {
val binding = UserListItemBinding.inflate(LayoutInflater.from(parent.context) , parent , false)
return UserListRecyclerViewHolder(binding)
}
override fun onBindViewHolder(holder: UserListRecyclerViewHolder, position: Int) {
holder.bind(userList[position])
}
override fun getItemCount() = userList.size
fun setList(list : MutableList<User>){
userList = list
}
/**
* Menu Item ์ ํ์ ํธ์ถ ๋ Listener๋ฅผ setting
**/
fun setOnMenuItemClickListener(listener: OnMenuItemClickListener){
mOnMenuItemClickListener = listener
}
/**
* RecyclierViewItem์ด ์ ํ์์ ํธ์ถ ๋ Listener๋ฅผ setting
**/
fun setOnItemClickListener(listener: OnItemClickListener){
mOnItemClickListener = listener
}
fun getSelectedUser() = mSelectedData // ์ ํ๋ Data๋ฅผ ListActivityd์์ ์ฌ์ฉํ๊ธฐ ์ํ ํจ์
inner class UserListRecyclerViewHolder(private val binding : UserListItemBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(data : User) {
with(binding){
userNameTextView.text = data.userName
userAgeTextViuew.text = data.userAge.toString()
}
val position = adapterPosition
if(position != RecyclerView.NO_POSITION){
mSelectedData = data
itemView.setOnLongClickListener { // Long Click์์ PopupMenu๋ฅผ ์์ฑ
val popupMenu = PopupMenu(binding.root.context , it)
popupMenu.menuInflater.inflate(R.menu.list_menu , popupMenu.menu)
popupMenu.setOnMenuItemClickListener(mOnMenuItemClickListener)
popupMenu.show()
true
}
itemView.setOnClickListener { // ์ค์ ํ ItemClickListener๋ฅผ ํธ์ถ
mOnItemClickListener?.onItemClick(it , data , position)
}
}
}
}
}
2-3. PopupMenu์ ์ฌ์ฉํ XML ์ ์
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/delete" android:title="์ญ์ ํ๊ธฐ"/>
</menu>
3. RecyclerView ์์ดํ ์ ํ ์ ๋ํ๋๋ UpdateActivity
class UpdateActivity : AppCompatActivity() {
private lateinit var binding : ActivityUpdateBinding
private lateinit var mViewModel : ActivityMainViewModel
private var mUserInfo : User? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this , R.layout.activity_update)
mViewModel = ViewModelProvider(this , MainViewModelFactory(MainRepository.getInstance()))[ActivityMainViewModel::class.java]
init()
addListener()
observeData()
binding.updateActivityViewModel = mViewModel
}
/**
* ListActivity๋ก ๋ถํฐ ์ ๋ฌ๋ฐ์ User ๊ฐ์ฒด๋ฅผ ํตํด EditText์ ๊ฐ์ settingํ๋ค.
**/
private fun init() {
mUserInfo = intent?.extras?.getSerializable(EXTRA_SELECTED_USER) as User
with(mViewModel){
userName.value = mUserInfo!!.userName
userAge.value = mUserInfo!!.userAge.toString()
}
}
private fun addListener() {
/**
* ์
๋ ฅ๋ ์ ๋ณด์ ๋ฐ๋ผ User๋ฅผ updateํ๋๋ก ํ๋ ๋์
**/
binding.updateButton.setOnClickListener {
val user = UserEntity(mUserInfo?.userId , mViewModel.userName.value!! , mViewModel.userAge.value!!.toInt())
mViewModel.updateUser(user)
}
}
private fun observeData() {
with(mViewModel){
message.observe(this@UpdateActivity){
Toast.makeText(MainApplication.getInstance() , it , Toast.LENGTH_SHORT).show()
}
}
}
}
โ๏ธ ์์์ ์ธ๊ธํ๋ฏ ํด๋น Activity๋ ActivityMain์ ViewModel์ ํจ๊ป ์ฐ๋๋ก ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก ์ ๋ฐ์ ์ธ ์คํํ๋ฉด์ ๋์ผ๋ก ํฌ์คํ ์ ๋ง์น๋๋ก ํ๊ฒ ์ต๋๋ค.
์ค๋๋ ์ฆ์ฝํ์ธ์ :)