Room์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํด ์ค์ผ ํจ.
plugins์ dependencies์ ์๋์ ๊ฐ์ด ์ฝ๋๋ฅผ ์ถ๊ฐํด ์ค.
build.gradle (module)
plugins {
...
id 'kotlin-kapt'
}
android {
...
}
dependencies {
...
// room
def roomVersion = "2.4.3"
implementation "androidx.room:room-ktx:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
}
Room์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ 3๊ฐ์ ํ์ผ(Dao, Database, Entity)์ ๋ง๋ค์ด ์ค์ผ ํจ.
Entity๋ ์ ์ ์ฐ๋ฆฌ๊ฐ ์ผ๋ NoteEntity ํ์ผ์ ๊ทธ๋๋ก ์ฐ๊ณ ์ฉ๋๋ ๋ฐ์ดํฐ ํด๋์ค,
Dao๋ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ, ์์ , ์ญ์ ๋ฑ์ ์ํ ์ฟผ๋ฆฌ๋ฌธ ์์ฑ์ ์ฐ์ผ ๊ฒ์ด๊ณ
Database๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ง๋๋ ์ญํ ์ ํจ.
๋๋ Room ํ์ผ๋ค์ ๊ตฌ๋ถํ๊ธฐ ์ฝ๊ฒ room ํจํค์ง๋ฅผ ๋ง๋ค์ด์คฌ์.

NoteEntity.kt
package com.ta2gi.note.room
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
// tableName์ ํ
์ด๋ธ๋ช
์ด๋ฉฐ ์์ด๋ค๋ฉด ํด๋์ค๋ช
์ด ํ
์ด๋ธ๋ช
์ด ๋จ
@Entity(tableName = "NoteTable")
data class NoteEntity(
// ๊ณ ์ ํค ๊ฐ, autoGenerate๋ ์๋์ผ๋ก ์ฆ๊ฐ์ํด
@PrimaryKey(autoGenerate = true)
val uid : Int?,
// ColumnInfo์ ์ปฌ๋ผ๋ช
์ ๋ณ์๋ช
๊ทธ๋๋ก ์ฌ์ฉํจ, ๋ฐ๋ก ์ด๋ฆ์ ๋ถ์ผ์๋ ์์
@ColumnInfo
val note : String,
@ColumnInfo
val date : String,
@ColumnInfo
val color : String
)
NoteDao.kt
package com.ta2gi.note.room
import androidx.room.*
@Dao
interface NoteDao {
// ๋
ธํธ ๊ฐ์ ธ์ค๊ธฐ
@Query("SELECT * FROM NoteTable")
fun getNote() : MutableList<NoteEntity>
// ๋
ธํธ ์ถ๊ฐ
@Insert
fun insertNote(note : NoteEntity)
// ๋
ธํธ ์์
@Update
fun updateNote(note : NoteEntity)
}
NoteDatabase.kt
package com.ta2gi.note.room
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [NoteEntity::class], version = 1)
abstract class NoteDatabase : RoomDatabase() {
abstract fun noteDao() : NoteDao
// ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ฑ ํ๋ฒ๋ง ์์ฑํ๊ฒ ๋ค๋ ์ฝ๋
companion object {
private var instance : NoteDatabase? = null
@Synchronized
fun getInstance(context: Context): NoteDatabase? {
if (instance == null) {
synchronized(NoteDatabase::class) {
instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java,
"note.db"
).build()
}
}
return instance
}
}
}
์ด์ ๋ฉ๋ชจ ์ถ๊ฐ, ์์ ๋ถ๋ถ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํด ๋ด.
๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ ๋ ์ฐ๋ ๋๋ฅผ ์จ์ผ ํจ.
์ฌ๊ธฐ๊น์ง์ ์ฝ๋๋ค์ ์ฌ๋ฆฌ๊ฒ ์.
(๋ถ๋ถ ๋ถ๋ถ ์์ ํ ๊ณณ์ด ๋ง์ ๋ค์ ์ฌ๋ฆฌ๋ ๊ฒ๋๋ค..)
MainActivity.kt
package com.ta2gi.note
import android.app.Activity
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import com.ta2gi.note.databinding.ActivityMainBinding
import com.ta2gi.note.fragment.AddFragment
import com.ta2gi.note.fragment.DetailFragment
import com.ta2gi.note.fragment.EditFragment
import com.ta2gi.note.fragment.HomeFragment
import com.ta2gi.note.room.NoteDatabase
import com.ta2gi.note.room.NoteEntity
class MainActivity : AppCompatActivity() {
lateinit var mainBinding: ActivityMainBinding
// ํ๋๊ทธ๋จผํธ๋ฅผ ๋ด์ ๋ณ์
lateinit var currentFragment: Fragment
// ๋
ธํธ ๋ฆฌ์คํธ
val noteList = mutableListOf<NoteEntity>()
// ์ด๋ํฐ
val noteAdapter = NoteAdapter(this, noteList)
// ๋
ธํธ ์์ ์นด์ดํธ
var noteCount = 0
// ํด๋ฆญํ ๋
ธํธ ์ ๋ณด
var noteText : String? = null
var noteDate : String? = null
var noteColor : String? = null
var noteUid : Int? = null
// ๋ฐ์ดํฐ๋ฒ ์ด์ค
lateinit var noteDatabase : NoteDatabase
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(mainBinding.root)
// ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ
noteDatabase = NoteDatabase.getInstance(this)!!
// ์ด๊ธฐํ๋ฉด
fragmentController("home", add = false)
}
// ํ๋๊ทธ๋จผํธ
fun fragmentController(view: String, add: Boolean) {
// ๋ค์ด์ค๋ view ๊ฐ์ ๋ฐ๋ผ ํ๋๊ทธ๋จผํธ ๋ณ๊ฒฝ
when (view) {
"home" -> currentFragment = HomeFragment(this)
"add" -> currentFragment = AddFragment(this)
"detail" -> currentFragment = DetailFragment(this)
"edit" -> currentFragment = EditFragment(this)
}
// ํ๋๊ทธ๋จผํธ ๊ต์ฒด ํด์ฃผ๊ธฐ
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.mai_screen, currentFragment)
// ๋ฐฑ์คํ
์ ์ถ๊ฐ
if (add) fragmentTransaction.addToBackStack(view)
// ์ ๋๋ฉ์ด์
ํจ๊ณผ ๋ฃ๊ธฐ
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
// ํ๋๊ทธ๋จผํธ ์คํ
fragmentTransaction.commit()
}
// ํค๋ณด๋ ๋ด๋ฆฌ๊ธฐ
fun hideKeyboard(act : Activity){
val imm = act.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(act.currentFocus?.windowToken, 0)
}
// ๋
ธํธ ์์
fun noteColor() : String {
var noteColor = ""
// 7์ด ๋๋ฉด 0๋ถํฐ ๋ค์ ์์
if(noteCount == 7) noteCount = 0
when (noteCount) {
// ๋นจ, ์ฃผ, ๋
ธ, ์ด, ํ, ๋จ, ๋ณด
0 -> noteColor = "#E53935"
1 -> noteColor = "#F4511E"
2 -> noteColor = "#FFB300"
3 -> noteColor = "#00897B"
4 -> noteColor = "#1E88E5"
5 -> noteColor = "#3949AB"
6 -> noteColor = "#5E35B1"
}
noteCount++
return noteColor
}
}
HomeFragment.kt
package com.ta2gi.note.fragment
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ta2gi.note.MainActivity
import com.ta2gi.note.R
import com.ta2gi.note.databinding.FragmentHomeBinding
import kotlin.concurrent.thread
class HomeFragment(val mainActivity : MainActivity) : Fragment(), View.OnClickListener {
lateinit var homeBinding : FragmentHomeBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
homeBinding = FragmentHomeBinding.inflate(inflater)
// ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ ๋ ๋
ธํธ๋ค ๋ฆฌ์คํธ์ ์ถ๊ฐ ํ ์ด๋ํฐ์ ์๋ฆฌ๊ธฐ
thread {
mainActivity.noteList.clear()
mainActivity.noteList.addAll(mainActivity.noteDatabase.noteDao().getNote())
// ์ด๋ํฐ ๋ผ์ฐ๊ธฐ
homeBinding.homRecyclerview.adapter = mainActivity.noteAdapter
mainActivity.noteAdapter.notifyDataSetChanged()
}
// ํด๋ฆญ ์ด๋ฒคํธ๊ฐ ์๋ ์น๊ตฌ๋ค์ setOnClickListener๋ฅผ ๋ฌ์์ค์ผ ํจ
homeBinding.homAdd.setOnClickListener(this)
return homeBinding.root
}
override fun onClick(view : View?) {
when(view) {
// ์ถ๊ฐ ๋ฒํผ
// +๋ฅผ ๋๋ฅด๋ฉด AddFragment๋ก ์ด๋
homeBinding.homAdd -> mainActivity.fragmentController("add", true)
}
}
}
AddFragment.kt
package com.ta2gi.note.fragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ta2gi.note.MainActivity
import com.ta2gi.note.room.NoteEntity
import com.ta2gi.note.databinding.FragmentAddBinding
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.thread
class AddFragment(val mainActivity : MainActivity) : Fragment(), View.OnClickListener {
lateinit var addBinding : FragmentAddBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
addBinding = FragmentAddBinding.inflate(inflater)
addBinding.addCancel.setOnClickListener(this)
addBinding.addComplete.setOnClickListener(this)
return addBinding.root
}
override fun onClick(view : View?) {
when(view) {
// ๋์๊ฐ๊ธฐ ๋ฒํผ
// ์ด์ ์ ํ๋๊ทธ๋จผํธ๋ก ๋์๊ฐ๊ธฐ
addBinding.addCancel -> mainActivity.supportFragmentManager.popBackStack()
// ์๋ฃ ๋ฒํผ
addBinding.addComplete -> {
// ํ
์คํธ์ ์ ํ ๋ด์ฉ ๊ฐ์ ธ์ค๊ธฐ
val editText = addBinding.addEdittext.text.toString()
// ์ค๋ ๋ ์ง ๊ฐ์ ธ์ค๊ธฐ(์์ฑ์ผ)
val sdf = SimpleDateFormat("yyyy.MM.dd", Locale.KOREAN)
val date = sdf.format(System.currentTimeMillis())
// ๋
ธํธ ์์ ์ ํ๊ธฐ
val noteColor = mainActivity.noteColor()
// ๋
ธํธ ์ ๋ณด ๊ฐ์ฒด์ ๋ฃ๊ธฐ
val entity = NoteEntity(null, editText, date, noteColor)
// ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋
ธํธ ์ถ๊ฐ
thread {
mainActivity.noteDatabase.noteDao().insertNote(entity)
// ์ด๋ํฐ์ ๋ฆฌ์คํธ ๋ณ๊ฒฝ ์ฌํญ ์๋ ค์ฃผ๊ณ ํค๋ณด๋ ๋ด๋ฆฌ๊ธฐ
mainActivity.noteAdapter.notifyDataSetChanged()
mainActivity.hideKeyboard(mainActivity)
mainActivity.supportFragmentManager.popBackStack()
}
}
}
}
}
DetailFragment.kt
package com.ta2gi.note.fragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ta2gi.note.MainActivity
import com.ta2gi.note.R
import com.ta2gi.note.databinding.FragmentDetailBinding
class DetailFragment(val mainActivity : MainActivity) : Fragment(), View.OnClickListener {
lateinit var detailBinding: FragmentDetailBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
detailBinding = FragmentDetailBinding.inflate(inflater)
detailBinding.detTitle.text = mainActivity.noteDate
detailBinding.detText.text = mainActivity.noteText
detailBinding.detCancel.setOnClickListener(this)
detailBinding.detEdit.setOnClickListener(this)
return detailBinding.root
}
override fun onClick(view : View?) {
when(view) {
// ๋์๊ฐ๊ธฐ ๋ฒํผ
detailBinding.detCancel -> {
// ํ ํ๋ฉด์ผ๋ก ๋์๊ฐ๋ฉด์ ํด๋ฆญํ๋ ๋
ธํธ์ ์ ๋ณด๋ฅผ ์ด๊ธฐํ
mainActivity.noteUid = null
mainActivity.noteText = null
mainActivity.noteDate = null
mainActivity.noteColor = null
mainActivity.supportFragmentManager.popBackStack()
}
// ์์ ํ๊ธฐ ๋ฒํผ
detailBinding.detEdit -> mainActivity.fragmentController("edit", true)
}
}
// ์์ ํ๊ณ ๋์์จ ํ ์์ ๋ ํ
์คํธ๋ก ๋ฐ๊พธ๊ธฐ ์ํ ์ฉ๋
override fun onResume() {
super.onResume()
detailBinding.detText.text = mainActivity.noteText
}
}
EditFragment.kt
package com.ta2gi.note.fragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ta2gi.note.MainActivity
import com.ta2gi.note.room.NoteEntity
import com.ta2gi.note.databinding.FragmentEditBinding
import kotlin.concurrent.thread
class EditFragment(val mainActivity : MainActivity) : Fragment(), View.OnClickListener {
lateinit var editBinding : FragmentEditBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
editBinding = FragmentEditBinding.inflate(inflater)
// ์์ ํ ํ
์คํธ ๊ฐ์ ธ์ค๊ธฐ
editBinding.ediEdittext.setText(mainActivity.noteText)
editBinding.ediCancel.setOnClickListener(this)
editBinding.ediComplete.setOnClickListener(this)
return editBinding.root
}
override fun onClick(view : View?) {
when(view) {
// ๋์๊ฐ๊ธฐ ๋ฒํผ
editBinding.ediCancel -> mainActivity.supportFragmentManager.popBackStack()
// ์๋ฃ ๋ฒํผ
editBinding.ediComplete -> {
// ํ
์คํธ์ ์ ํ ๋ด์ฉ ๊ฐ์ ธ์ค๊ธฐ
val editText = editBinding.ediEdittext.text.toString()
// ์์ ํ ๋
ธํธ ์ ๋ณด ๊ฐ์ฒด์ ๋ฃ๊ธฐ
val entity = NoteEntity(mainActivity.noteUid!!, editText, mainActivity.noteDate!!, mainActivity.noteColor!!)
thread {
mainActivity.noteDatabase.noteDao().updateNote(entity)
// ์๋ฃํ๊ณ ๋์๊ฐ ๋ ํ๋๊ทธ๋จผํธ ํ
์คํธ๋ฅผ ์์ ํ ํ
์คํธ๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ
mainActivity.noteText = editText
// ์ด๋ํฐ์ ๋ฆฌ์คํธ ๋ณ๊ฒฝ ์ฌํญ ์๋ ค์ฃผ๊ณ ํค๋ณด๋ ๋ด๋ฆฌ๊ธฐ
mainActivity.noteAdapter.notifyDataSetChanged()
mainActivity.hideKeyboard(mainActivity)
mainActivity.supportFragmentManager.popBackStack()
}
}
}
}
}
NoteAdapter.kt
package com.ta2gi.note
import android.content.res.ColorStateList
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.ta2gi.note.room.NoteEntity
class NoteAdapter(val mainActivity : MainActivity, val noteList : MutableList<NoteEntity>) : RecyclerView.Adapter<NoteAdapter.ViewHolderClass>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteAdapter.ViewHolderClass {
// ํญ๋ชฉ์ layout์ R.layout.list_item
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return ViewHolderClass(view)
}
override fun onBindViewHolder(holder: NoteAdapter.ViewHolderClass, position: Int) {
// ๋
ธํธ ๋ด์ฉ ๋ฃ๊ธฐ
holder.note.text = noteList[position].note
// ๋
ธํธ ์์ ๋ฃ๊ธฐ
holder.background.backgroundTintList = ColorStateList.valueOf(Color.parseColor(noteList[position].color))
holder.note.setOnClickListener {
// ํด๋ฆญํ ๋
ธํธ ์ ๋ณด ๋ด๊ณ ํ๋๊ทธ๋จผํธ ์ด๋
mainActivity.noteUid = noteList[position].uid
mainActivity.noteText = holder.note.text.toString()
mainActivity.noteDate = noteList[position].date
mainActivity.noteColor = noteList[position].color
mainActivity.fragmentController("detail", true)
}
}
override fun getItemCount(): Int {
// ๋ฆฌ์คํธ์ ๋ด๊ธด ํญ๋ชฉ์ ํฌ๊ธฐ๋งํผ ๋์ค๊ฒํ๊ธฐ
return noteList.size
}
inner class ViewHolderClass(view : View) : RecyclerView.ViewHolder(view) {
val background = view.findViewById<LinearLayout>(R.id.ite_layout)
val note = view.findViewById<TextView>(R.id.ite_text)
}
}
์ฌ๊ธฐ๊น์ง๋ง ํ๋ฉด ๋ชจ๋ ๊ฒ ์ ๋์๊ฐ.
๋ค์ ๊ธ์์๋ ์ญ์ ๊ธฐ๋ฅ์ ๋ฃ์ด๋ณด๋๋ก ํ๊ฒ ์.
To be Continued..๐ง
'๐ฑ > ๐Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Kotlin] ๋์ ๊ฒ์ ์ฑ ๋ง๋ค๊ธฐ๏ผ (0) | 2023.01.26 |
---|---|
[Kotlin] Note ์ฑ ๋ง๋ค๊ธฐ๏ผ (0) | 2023.01.11 |
[Kotlin] Note ์ฑ ๋ง๋ค๊ธฐ๏ผ (0) | 2023.01.10 |
[Kotlin] Note ์ฑ ๋ง๋ค๊ธฐ๏ผ (0) | 2023.01.09 |
[Kotlin] TodoList ์ฑ ๋ง๋ค๊ธฐ๏ผ (0) | 2023.01.03 |