리사이클러뷰에 DB정보 읽어오기

Hwan·2023년 6월 15일
0

GiftMap

목록 보기
12/15

구현할 내용

  • DB에 저장된 정보값을 이용하여 이미지와 정보 가져오기

총체적으로 갈아엎어서 내용이 자잘자잘하게 많다...

1. build.gradle

새 정보가 올라오면 자동으로 업데이트 하기 위해 아래 라이브러리를 가져온다.

implementation "androidx.lifecycle:lifecycle-viewmodel:2.4.0"
implementation "androidx.lifecycle:lifecycle-livedata:2.4.0"

2. ItemData.kt 생성

data class ItemData(val store: String = "가게명", val date: String = "유효기간", val item: String = "상품명", val image_url: String = "")

3. Repo.kt 생성

datasource를 캡슐화 하는 코드

class Repo {
    fun getData(): LiveData<MutableList<ItemData>> {
        val mutableData = MutableLiveData<MutableList<ItemData>>()
        val database = Firebase.database
        val myRef = database.getReference("user_data")
        myRef.addValueEventListener(object : ValueEventListener {
            val listData: MutableList<ItemData> = mutableListOf<ItemData>()
            override fun onDataChange(snapshot: DataSnapshot) {
                if (snapshot.exists()){
                    for (userSnapshot in snapshot.children){
                        val getData = userSnapshot.getValue(ItemData::class.java)
                        listData.add(getData!!)

                        mutableData.value = listData
                    }
                }
            }
            override fun onCancelled(error: DatabaseError) {
                TODO("Not yet implemented")
            }
        })
        return mutableData
    }
}

4. ListViewModel.kt 생성

repo에 있는 데이터를 관찰하고 있다가, 데이터가 변경되면 mutableData의 값을 변경시켜준다.

class ListViewModel : ViewModel() {
    private val repo = Repo()
    fun fetchData(): LiveData<MutableList<ItemData>> {
        val mutableData = MutableLiveData<MutableList<ItemData>>()
        repo.getData().observeForever{
            mutableData.value = it
        }
        return mutableData
    }
}

5. ImageAdapter.kt

ImageAdapter의 items를 String에서 ItemData로 바꾸고 많은 것을 수정했다. 최종 코드는 아래와 같음.

class ImageAdapter(private val items: ArrayList<ItemData>) : RecyclerView.Adapter<ImageAdapter.ViewHolder>() {

    private var isMultiSelect = false
    private val selectedItems = mutableListOf<String>()
    private var giftList = ArrayList<ItemData>()
    private val storageRef = FirebaseStorage.getInstance().reference
    private val databaseRef = Firebase.database.getReference("user_data")

    fun toggleMultiSelect() {
        isMultiSelect = !isMultiSelect
        if (isMultiSelect) {
            notifyDataSetChanged()
            selectedItems.clear()
        } else {
            deleteSelectedItems()
        }
    }

    private fun deleteSelectedItems() {
        // 선택된 이미지들에 대해 firebase storage와 DB에서 삭제
        selectedItems.forEach { imageUrl ->
            // 파일 경로에서 파일 이름만 추출
            val filename = imageUrl.substringAfterLast("%2F")
                .substringBeforeLast("?")
            Log.d("ImageAdapter", filename)

            // firebase storage에서 해당 이미지 삭제
            storageRef.child("images/$filename").delete()

            // firebase DB에서 해당 데이터 삭제
            databaseRef.orderByChild("image_url").equalTo("/images/$filename").addListenerForSingleValueEvent(object :
                ValueEventListener {
                override fun onDataChange(dataSnapshot: DataSnapshot) {
                    for (snapshot in dataSnapshot.children) {
                        snapshot.ref.removeValue()
                    }
                }

                override fun onCancelled(databaseError: DatabaseError) {
                    Log.d("ImageAdapter", "onCancelled: ${databaseError.toException()}")
                }
            })

            // 선택한 이미지 리스트에서 삭제
            val index = selectedItems.indexOf(imageUrl)
            items.removeAt(index)
        }

        // 선택된 아이템 초기화
        selectedItems.clear()
        isMultiSelect = false

        // 어댑터 갱신
        notifyDataSetChanged()
    }

    fun setListData(data: MutableList<ItemData>) {
        giftList.clear()
        giftList.addAll(data)
        notifyDataSetChanged()
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val imageView: ImageView = itemView.findViewById(R.id.img)
        val store: TextView = itemView.findViewById(R.id.store)
        val item: TextView = itemView.findViewById(R.id.item)
        val date: TextView = itemView.findViewById(R.id.date)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.giftlist, parent, false)
        return ViewHolder(view)
    }

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val gift: ItemData = giftList[position]
        holder.store.text = gift.store
        holder.item.text = gift.item
        holder.date.text = gift.date

        val imageUrl = gift.image_url
        Log.v(TAG, "image = " + storageRef.child(imageUrl))
        Glide.with(holder.imageView.context).load(storageRef.child(imageUrl)).into(holder.imageView)


        if (isMultiSelect) {
            val isSelected = selectedItems.contains(gift.image_url)
            holder.itemView.setBackgroundColor(
                if (isSelected) {
                    ContextCompat.getColor(holder.itemView.context, R.color.selectpink)
                } else {
                    Color.TRANSPARENT
                }
            )

            holder.itemView.setOnClickListener {
                if (isSelected) {
                    selectedItems.remove(gift.image_url)
                } else {
                    selectedItems.add(gift.image_url)
                }
                notifyItemChanged(position)
            }
        } else {
            holder.itemView.setBackgroundColor(Color.TRANSPARENT)
            holder.itemView.setOnClickListener(null)
        }
    }
}

6. ManageActivity.kt

마찬가지로 많은 부분이 빠져서 최종코드. imageList가 ItemData의 ArrayList로 바뀌었다.

class ManageActivity : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter : ImageAdapter
    private val viewModel by lazy {ViewModelProvider(this).get(ListViewModel::class.java)}
    private lateinit var imageList: ArrayList<ItemData>

    private val storageRef = FirebaseStorage.getInstance().getReference("images")
    private val databaseRef = FirebaseDatabase.getInstance().reference.child("user_data")

    private var isMultiSelect = false

    private lateinit var addbtn: Button
    private lateinit var editbtn: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_manage)

        addbtn = findViewById(R.id.button1)
        editbtn = findViewById(R.id.button2)

        // 기프티콘 업로드, 삭제
        addbtn.setOnClickListener {
            if (isMultiSelect) {
                toggleMultiSelect()
            } else {
                val intent = Intent(this, UploadActivity::class.java)
                startActivityForResult(intent, REQUEST_CODE)
            }
        }
        editbtn.setOnClickListener{
            toggleMultiSelect()
        }

        // 리사이클러뷰 이미지
        recyclerView = findViewById(R.id.listgift)
        recyclerView.layoutManager = LinearLayoutManager(this)

        imageList = ArrayList()
        adapter = ImageAdapter(imageList)
        recyclerView.adapter = adapter

        observerData()
    }

    fun observerData(){
        viewModel.fetchData().observe(this, { data ->
            imageList.clear()
            imageList.addAll(data)
            adapter.setListData(data)
            adapter.notifyDataSetChanged()
        })
    }

    private fun toggleMultiSelect() {
        isMultiSelect = !isMultiSelect
        if (isMultiSelect) {
            addbtn.text = "취소"
            editbtn.text = "삭제"
        } else {
            addbtn.text = "추가"
            editbtn.text = "편집"
        }
        adapter.toggleMultiSelect()
    }

    companion object {
        private const val REQUEST_CODE = 100
    }

}

0개의 댓글