if (!it.exists())을 추가하여 존재하지 않은 경우에만 새롭게 추가하도록 만들어주었다. 이를 통해 파이어베이스 쓰기 비용도 꼭 필요한 경우에만 사용된다.어제 CampDetail에서 북마크를 추가할 수 있는 기능을 만들었으니, 오늘은 프로필 화면에서 내가 북마크한 목록을 확인 할 수 있도록 만들었다.
//ProfileFragment.kt
private fun setBookmarkedAdapter(userId : String) = with(binding) {
rvBookmarked.adapter = adapter
rvBookmarked.layoutManager = LinearLayoutManager(requireContext(),LinearLayoutManager.VERTICAL,false)
viewModel.getBookmark(userId)
viewModel.bookmarkedList.observe(viewLifecycleOwner){
adapter.submitList(it)
if(it.isNotEmpty()) {
tvBookmarkedSize.visibility =View.VISIBLE
tvTabBookmarked.visibility =View.GONE
rvBookmarked.visibility = View.VISIBLE
tvBookmarkedSize.text = it.size.toString()
} else{
tvTabBookmarked.visibility =View.VISIBLE
rvBookmarked.visibility = View.GONE
tvBookmarkedSize.text = it.size.toString()
}
}
}
목록은 리사이클러뷰 어댑터를 활용하여 화면에 뿌려줄 것이다. 이를 위해 ListAdapter를 만들어주었고, 그 안에서 북마크 목록의 아이템을 클릭하면 상세페이지로 넘어갈 수 있도록 아이템 클릭 이벤트도 만들어주었다.
class ProfileBookmarkAdapter : ListAdapter<CampEntity, ProfileBookmarkAdapter.Holder>(diffUtil) {
inner class Holder(val binding: ItemBookmarkedBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(data: CampEntity) {
with(binding) {
if (data.firstImageUrl.isNullOrBlank()) {
ivCampImg.setImageResource(R.drawable.default_camping)
} else {
Glide.with(binding.root).load(data.firstImageUrl).into(binding.ivCampImg)
}
tvCampName.text = data.facltNm
tvCampAddr.text = data.addr1
if (data.lctCl.toString() == "[]") {
tvCampType.text = "[일반]"
} else {
tvCampType.text = data.lctCl.toString()
}
tvCampInduty.text = data.induty.toString()
binding.root.setOnClickListener {
val myData = CampEntity(
addr1 = data.addr1,
contentId = data.contentId,
...
themaEnvrnCl = data.themaEnvrnCl
)
val intent = Intent(binding.root.context, CampDetailActivity::class.java).apply {
putExtra("campData", myData)
}
binding.root.context.startActivity(intent)
}
}
}
}
companion object {
private val diffUtil = object : DiffUtil.ItemCallback<CampEntity>() {
override fun areItemsTheSame(oldItem: CampEntity, newItem: CampEntity): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: CampEntity, newItem: CampEntity): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val binding = ItemBookmarkedBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val item = getItem(position)
holder.bind(item)
}
}
북마크 목록을 가져오는 것은 MVVM 패턴을 활용하여 만들었다. 상세 페이지로 캠핑장 전체 데이터를 intent해서 넘겨주어야 하기 때문에, 북마크로 저장하고 있는 contentID를 통해 캠핑장 정보 자체를 담을 수 있도록 데이터 가공을 거쳐서 저장을 해야한다.
class ProfileViewModel : ViewModel() {
private val _bookmarkedList: MutableLiveData<List<CampEntity>> = MutableLiveData()
val bookmarkedList: LiveData<List<CampEntity>> get() = _bookmarkedList
private val bookmarkCamp: MutableList<CampEntity> = mutableListOf()
fun getBookmark(userID: String) {
Timber.tag("겟북마크검사").d("작동중")
val db = FirebaseFirestore.getInstance()
val docRef = db.collection("users").document("Kakao${userID}")
val contentIds = mutableListOf<String>()
docRef.get().addOnSuccessListener {
if (it.exists()) {
val bookmarkData = it.get("bookmarked") as? List<*>
Timber.tag("겟북마크목록검사").d(bookmarkData.toString())
if (bookmarkData != null) {
for (item in bookmarkData) {
contentIds.add(item.toString())
}
Timber.tag("북마크목록검사").d("$contentIds")
}
bookmarkCamp.clear()
if (contentIds.isNotEmpty()) {
callBookmarkCamp(contentIds)
}
}
}
}
private fun callBookmarkCamp(bookmarkedItemList: MutableList<String>) {
val db = Firebase.firestore
val baseQuery: Query = db.collection("camps")
val result = baseQuery.whereIn("contentId", bookmarkedItemList)
result.get().addOnSuccessListener {
for (doc in it) {
val camp = doc.toObject(CampEntity::class.java)
bookmarkCamp.add(camp)
}
_bookmarkedList.value = bookmarkCamp
Timber.tag("콜북마크검사").d(bookmarkCamp.size.toString())
}
}
}
whereIn의 경우는 null이 들어오면 강제종료되는 이슈가 있었다. 그래서 getBookmark함수에서 if (contentIds.isNotEmpty())을 통해 null이 아닐 때만 callBookmarkCamp가 작동할 수 있도록 고쳐주었다.getBookmark()에서 bookmarkCamp.clear()를 해주지 않았더니, 매번 불러오는 북마크 리스트가 중복 누적되는 것을 발견했다.private fun handleClickEdit(confirm: Boolean) {
with(binding) {
if (confirm) {
//Todo. 사진에 대한 변경값을 다시 스토리지를 통헤 데이터베이스에 넘겨서 저장
UserApiClient.instance.me { user, error ->
val documentRef = db.collection("users").document("Kakao${user?.id}")
val updateNickname = hashMapOf<String, Any>("nickName" to "${tvProfileName.text}")
//val updateProfileImg = hashMapOf<String,Any>("profileImage" to img_URI.toString())
documentRef.get().addOnSuccessListener {
documentRef.update(updateNickname)
//documentRef.update(updateProfileImg)
}
}
tvProfileName.text = tvProfileName.text
//ivProfileImg.setImageURI(img_URI)
} else {
tvProfileName.text = ""
initLogin()
}
...
if(rvBookmarked.visibility == View.VISIBLE){
tvTabBookmarked.visibility = View.GONE
}
}
}