구현할 내용
- DB에 저장된 정보값을 이용하여 이미지와 정보 가져오기
총체적으로 갈아엎어서 내용이 자잘자잘하게 많다...
새 정보가 올라오면 자동으로 업데이트 하기 위해 아래 라이브러리를 가져온다.
implementation "androidx.lifecycle:lifecycle-viewmodel:2.4.0"
implementation "androidx.lifecycle:lifecycle-livedata:2.4.0"
data class ItemData(val store: String = "가게명", val date: String = "유효기간", val item: String = "상품명", val image_url: String = "")
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
}
}
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
}
}
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)
}
}
}
마찬가지로 많은 부분이 빠져서 최종코드. 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
}
}