📌 학습 목표
- Database(DB)에 대해 설명할 수 있다.
- DBMS의 의미와 종류(관계형, 비관계형)를 설명할 수 있다.
- Key-Value를 사용하는 자료구조에 대해 설명할 수 있다.
- Android에서의 데이터 저장 방법을 설명하고 사용할 수 있다.
📝 Standard Mission
1. RoomDB를 이용하여 5주차 RecyclerView의 Standard Misson에서 만들었던 메모장 앱의 메모들이 앱이 껐다 켜져도 유지 (저장)되도록 하기
먼저, RoomDB를 사용하기 전에 build.gradle 파일을 수정해줘야 한다.
아래 내용을 추가하고 난 뒤, 싱크를 맞춰준다!
다음으로 RoomDB를 살펴보자면
AppDatabase.kt
package com.example.homework5.Room
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
// DB 와 객체를 넣는 과정
// 여러 클래스가 들어올 수 있으니 배열, 업데이트 될 수도 있으니 버전
@Database(entities = [Memo::class], version = 1)
abstract class AppDatabase: RoomDatabase() {
// 자동으로 Dao 값 채워줌
abstract fun memoDao(): MemoDao
// 싱글톤 패턴 (하나의 앱에서 사용될 때 DB 하나를 전역적으로 재활용)
companion object {
// database 가 담기는 객체
private var appDatabase: AppDatabase? = null
@Synchronized // 여러 스레드에서 하나의 자원에 접근하려고 할 때 그것을 방지
fun getInstance(context: Context): AppDatabase? {
if(appDatabase == null) { // null 일 때 초기화 해줘야함
synchronized(AppDatabase::class.java){ // 이 클래스가 점유하고 있다는 뜻
appDatabase = Room.databaseBuilder(
context.applicationContext, // 전역적
AppDatabase::class.java,
"app-database", // 이름 다 다르게
).allowMainThreadQueries().build()
}
}
return appDatabase
}
}
}
Memo.kt
package com.example.homework5.Room
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity // RoomDB 에서 사용되는 객체라는 것을 알리기 위해
data class Memo(
@ColumnInfo(name="memo") val memo: String,
// 고유키 autoGenerate 자동으로 증가
@PrimaryKey(autoGenerate = true) @ColumnInfo(name="memoId") val memoId: Int = 0
)
MemoDao.kt
package com.example.homework5.Room
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
@Dao
interface MemoDao {
@Insert
fun insert(memo: Memo)
@Delete
fun delete(memo: Memo)
// 가져오는 것
@Query("SELECT * FROM Memo")
fun selectAll(): List<Memo>
}
MainActivity.kt
package com.example.homework5
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.homework5.Recycler.MemoRVAdapter
import com.example.homework5.Room.AppDatabase
import com.example.homework5.Room.Memo
import com.example.homework5.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var getResultText: ActivityResultLauncher<Intent>
private val memoList: ArrayList<Memo> = arrayListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// DB 초기화
val roomDb = AppDatabase.getInstance(this)
// 이전에 저장한 내용 모두 불러와서 추가하기
if(roomDb != null) {
val savedMemo = roomDb.memoDao().selectAll()
memoList.addAll(savedMemo)
}
// position 을 전달받고 삭제 함수 실행
val dataRVAdapter = MemoRVAdapter(memoList, onClickDeleteBtn = {
if (roomDb != null) { // DB 에서 삭제
roomDb.memoDao().delete(it)
}
deleteTask(it) // 리스트뷰에서 삭제
})
// ActivityResult 를 받기 위한 Callback 등록
getResultText =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
if(roomDb != null) {
val mString = result.data?.getStringExtra("data") ?: ""
// DB 에 삽입
val memo = Memo("${mString}")
roomDb.memoDao().insert(memo)
// 리스트뷰에 삽입
memoList.apply {
add(Memo("$mString"))
}
// 리스트뷰 갱신
dataRVAdapter.notifyItemRangeInserted(memoList.size, 1) // 변경된 아이템의 시작 위치, 변경된 아이템 개수
}
}
}
// 메모 추가 버튼 누르면 메모 화면으로 넘어가는 것 && 위에서 정의한 것을 launch 함수로 시작
binding.btnAdd.setOnClickListener {
val mintent = Intent(this@MainActivity, MemoActivity::class.java)
getResultText.launch(mintent)
}
binding.rvData.adapter = dataRVAdapter // 리사이클러뷰에 어댑터 연결
binding.rvData.layoutManager = LinearLayoutManager(this) // 레이아웃 매니저 연결
}
fun deleteTask(data: Memo) {
memoList.remove(data)
binding.rvData.adapter?.notifyDataSetChanged()
}
}
MemoActivity.kt
package com.example.homework5
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.homework5.databinding.ActivityMainBinding
import com.example.homework5.databinding.ActivityMemoBinding
class MemoActivity : AppCompatActivity() {
private lateinit var viewBinding: ActivityMemoBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivityMemoBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
// MemoActivity 에서 MainActivity 로 data 전달
viewBinding.btnStore.setOnClickListener {
val mIntent = Intent(this, MainActivity::class.java).apply {
putExtra("data", viewBinding.edtText.text.toString())
}
setResult(RESULT_OK, mIntent)
if(!isFinishing) finish()
}
}
}
MemoRVAdapter.kt
어댑터는 특별히 수정한 건 없었다!
package com.example.homework5.Recycler
import android.view.LayoutInflater
import android.view.MenuItem.OnMenuItemClickListener
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.homework5.Room.Memo
import com.example.homework5.databinding.ItemDataBinding
// Adapter 인자에 데이터를 넣어주면, MainActivity 에서 수정하면 자동으로 수정됨
class MemoRVAdapter( private val memoList: ArrayList<Memo>, val onClickDeleteBtn: (data: Memo) -> Unit) :
RecyclerView.Adapter<MemoRVAdapter.DataViewHolder>() {
// ViewHolder 객체
inner class DataViewHolder(val binding: ItemDataBinding): RecyclerView.ViewHolder(binding.root) {
fun bind(data: Memo) {
binding.tvMemo.text = data.memo;
}
}
// ViewHolder 만들어질 때 실행할 동작
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataViewHolder {
val viewBinding = ItemDataBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return DataViewHolder(viewBinding)
}
// ViewHolder 가 실제로 데이터를 표시해야 할 때 호출되는 함수
override fun onBindViewHolder(holder: DataViewHolder, position: Int) {
val position = memoList[position]
holder.bind(position)
// deleteBtn 이 눌렸을 때 position 전달
holder.binding.deleteBtn.setOnClickListener {
onClickDeleteBtn.invoke(position)
}
}
// 표현할 Item 의 총 개수
override fun getItemCount(): Int = memoList.size
}
2. ShardPreference를 이용하여 메모 즐겨찾기 기능 구현하기
각각의 메모에 즐겨찾기 버튼 만들기 (누르면 보관함에서 그 메모를 확인 가능)
보관함 Activity는 새로 생성하기
'🍞 대외활동 > Univ Makeus Challenge' 카테고리의 다른 글
[UMC] Android 9주차 워크북 (Network) - Retrofit2 OpenAPI (0) | 2022.11.27 |
---|---|
[UMC] 3rd UMC 해커톤 회고 (0) | 2022.11.22 |
[UMC] Android 7주차 워크북 (Thread) (0) | 2022.11.17 |
[UMC] Android 6주차 워크북 (고급 Layout과 View) (0) | 2022.11.07 |
[UMC] Android 5주차 워크북 (RecyclerView) - 메모장 앱 (0) | 2022.10.24 |