KUIT-앱 개발 프로젝트 동아리

7주차실습(3)-room db&코루틴 응용

농농씨 2023. 11. 10. 21:46

지난 7주차 실습 프로젝트에서 그대로 할거임

 

지난 시간 복습

IO 스레드에서 돌아가는 코루틴 만들어서 데이터 추가

그리고 메인스레드로 돌아와서 say "데이터 다시 그려"

 

이번엔 변수가 아닌 데이터베이스에 데이터를 추가해서 가져와서 레이아웃으로 그려보겠다.

1. 데이터베이스 객체 수정

우선 데이터베이스 객체 파일인 MyStringDatabase.kt로 가서

.allowMainThreadQueries().build() // databaseBuilder() 뒤에 꼭 build() 붙여야함

이걸 지워줄거임

원래는 메인스레드에서 데이터베이스에 접근하는게 안됐는데 요청했었음.

이거 지웠으니 이제 메인스레드가 아닌 스레드에서만 데이터에 접근할수있음

2. MainActivity 수정

2-1. 데이터베이스 변수 설정

그럼 데이터베이스 변수가 필요할 거임

(일단 이구문 지워주고

dataList1.add(MyStringEntity("item" + count++))

)

var myStringDatabase : MyStringDatabase? = null // 데이터베이스 객체 만듦
(onCreate() 안에 있음

myStringDatabase = MyStringDatabase.getInstance(this)

얘네들 주석 해제

2-2. 데이터베이스 수정

myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item" + count++))

코루틴 안에 있는 while 문으로 가서 

database 변수에 있는 DAO객체를 이용해서 

Entity의 MyString 객체를 넣어줄 것이다.

 

2-3. 데이터 가져오기

myStringDatabase!!.getMyStringDAO().getAllMyStrings()

(변수 통해)데이터베이스에 접근해서 

DAO를 가져와서

getAllMyStrings()로 모든 데이터 가져올거임

 

그리고 그걸 dataList 변수에 넣을거임

val arrList = arrayListOf<MyStringEntity>()
arrList.addAll(myStringDatabase!!.getMyStringDAO().getAllMyStrings())
dataList1 = arrList

arrayList 변수 하나 더 설정해서 그걸로 저장함

 

그럼 그 결과는

IO 스레드에서 돌아가는 코루틴에게 say

1초기다렸다가 데이터베이스에 MyStringEntity아이템 하나 추가하셈 "item+count++"

그리고 DAO로 myStringEntity에 있는 모든 값 가져와 getAllMyStrings

그리고 그걸 데이터 리스트로 설정해 dataList

마지막으로, 바꾼 그 데이터를 적용해서 화면을 그려라

 

크게 달라진건 없고

데이터베이스에 데이터를 추가해서 가져오는 걸로 바뀜

 

근데 arrList를 한번 거쳐서 데이터를 출력하려다보니 리사이클러뷰가 인식을 못함

 

3. 리사이클러뷰 어댑터 수정

 

fun setData(list : List<MyStringEntity>) {
        items = list
        notifyDataSetChanged()
    }

함수추가해서 어떤 리스트를 전달하면 어댑터의 items를 그 리스트로 세팅하는

그런 내용의 함수를 별도로 선언해줌

그리고 데이터 바뀌었으니 ui 업데이트하라는 notifyDataSetChanged도 그 안에 선언해줌

 

// 어댑터 코드

package com.iyr.a7thweekpractice

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.iyr.a7thweekpractice.databinding.ItemHomeBinding

class JustAdapter(var items: List<MyStringEntity>): RecyclerView.Adapter<JustAdapter.ViewHolder>() {
    inner class ViewHolder(val binding : ItemHomeBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(item : MyStringEntity) {
            binding.tvItemHome.text = item.str
        }

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemHomeBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(items[position])
    }

    fun setData(list : List<MyStringEntity>) {
        items = list
        notifyDataSetChanged()
    }


}

 

4. 다시 MainActivity 수정

 

// MainActivity 최종 코드


package com.iyr.a7thweekpractice

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.iyr.a7thweekpractice.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.invoke
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class MainActivity : AppCompatActivity() {
    lateinit var binding : ActivityMainBinding

    var dataList1 = ArrayList<MyStringEntity>() // 초기화 해야함
//    var dataList2 : ArrayList<String> = arrayListOf() // null로 선언
    var myStringDatabase : MyStringDatabase? = null // 데이터베이스 객체 만듦
    var count = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        myStringDatabase = MyStringDatabase.getInstance(this)
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item0"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item1"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item2"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item3"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item4"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item5"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item6"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item7"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item8"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item9"))
//        myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item10"))
//
//        dataList1.addAll(myStringDatabase!!.getMyStringDAO().getAllMyStrings())


        CoroutineScope(Dispatchers.IO).launch {
            while (true) {
                delay(1000)
//                dataList1.add(MyStringEntity("item" + count++))
                myStringDatabase!!.getMyStringDAO().addMyString(MyStringEntity("item" + count++))

                val arrList = arrayListOf<MyStringEntity>()
                arrList.addAll(myStringDatabase!!.getMyStringDAO().getAllMyStrings())

                withContext(Dispatchers.Main) {
                    (binding.rvHome.adapter as JustAdapter).setData(arrList)
                }
                Log.d("coroutineScope", "코루틴작동")
            }
        }

        binding.rvHome.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        binding.rvHome.adapter = JustAdapter(dataList1)

    }
}

알고보니 dataList1에 arrList를 넣는 작업은 불필요했음

그냥 어댑터에 전달할 arrList만 사용됨

 

 

7주차 미션설명

이번에는 데이터를 roomdb에 넣어서 추가해볼거다