๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ฑ| Android/๐Ÿ”ฅ | Firebase

[Android, Kotlin] firebase sns ์•ฑ ๋งŒ๋“ค๊ธฐ 5(๊ฒŒ์‹œ๊ธ€ ์„ธ๋ถ€ ๊ธฐ๋Šฅ)

by immgga 2022. 10. 28.

์ด๋ฒˆ์—๋Š” ๊ฒŒ์‹œ๋ฌผ์˜ ์„ธ๋ถ€ ๊ธฐ๋Šฅ๋“ค์„ ๋งŒ๋“ค์–ด๋ณด๊ฒ ๋‹ค.


๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ recycler view item

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/post_user"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginStart="28dp"
        android:layout_marginBottom="8dp"
        android:background="@drawable/post_img"
        app:layout_constraintBottom_toTopOf="@+id/post_main_img"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/post_user_text"
        android:layout_width="230dp"
        android:layout_height="wrap_content"
        android:fontFamily="@font/cafe24ssurround"
        android:text="username"
        android:textSize="17sp"
        android:maxLines="1"
        android:ellipsize="end"
        android:layout_marginStart="20dp"
        app:layout_constraintBottom_toBottomOf="@+id/post_user"
        app:layout_constraintStart_toEndOf="@+id/post_user"
        app:layout_constraintTop_toTopOf="@+id/post_user" />

    <TextView
        android:id="@+id/post_timestamp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/cafe24ssurround"
        android:text="time"
        android:textSize="10sp"
        android:layout_marginEnd="30dp"
        app:layout_constraintBottom_toBottomOf="@+id/post_user_text"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/post_user_text" />

    <androidx.cardview.widget.CardView
        android:id="@+id/post_main_img"
        android:layout_width="350dp"
        android:layout_height="350dp"
        android:layout_marginTop="65dp"
        app:cardCornerRadius="20dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/post_main_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/post_img" />

    </androidx.cardview.widget.CardView>

    <View
        android:id="@+id/line"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#9A9A9A"
        android:layout_marginTop="15dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_main_img" />

    <ImageView
        android:id="@+id/like"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@drawable/hanger_unselected"
        app:layout_constraintStart_toStartOf="@+id/post_main_img"
        app:layout_constraintTop_toBottomOf="@+id/line" />

    <ImageView
        android:id="@+id/star"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginStart="12dp"
        android:src="@drawable/star_unselected"
        app:layout_constraintBottom_toBottomOf="@+id/like"
        app:layout_constraintStart_toEndOf="@+id/like"
        app:layout_constraintTop_toTopOf="@+id/like"
        app:layout_constraintVertical_bias="1.0" />

    <ImageView
        android:id="@+id/comment"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_marginStart="15dp"
        android:src="@drawable/comment_unselected"
        app:layout_constraintBottom_toBottomOf="@+id/star"
        app:layout_constraintStart_toEndOf="@+id/star"
        app:layout_constraintTop_toTopOf="@+id/star" />

    <ImageView
        android:id="@+id/bookmark"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/tag_unselected"
        app:layout_constraintEnd_toEndOf="@+id/post_main_img"
        app:layout_constraintTop_toTopOf="@+id/comment" />

    <TextView
        android:id="@+id/like_count"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/cafe24ssurround"
        android:text="0"
        app:layout_constraintEnd_toEndOf="@+id/like"
        app:layout_constraintStart_toStartOf="@+id/like"
        app:layout_constraintTop_toBottomOf="@+id/like" />

    <TextView
        android:id="@+id/post_str"
        android:layout_width="350dp"
        android:layout_height="100dp"
        android:text="์„ค๋ช…"
        android:fontFamily="@font/cafe24ssurround"
        android:textSize="20dp"
        android:textColor="@color/black"
        android:layout_marginTop="70dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/line" />

    <TextView
        android:id="@+id/hasi1_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:fontFamily="@font/cafe24ssurround"
        android:text="#์…”์ธ "
        android:textSize="15dp"
        app:layout_constraintStart_toStartOf="@+id/post_str"
        app:layout_constraintTop_toBottomOf="@+id/post_str" />

    <TextView
        android:id="@+id/hasi2_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:fontFamily="@font/cafe24ssurround"
        android:text="#๋งจํˆฌ๋งจ"
        android:layout_marginStart="15dp"
        android:textSize="15dp"
        app:layout_constraintStart_toEndOf="@+id/hasi1_text"
        app:layout_constraintTop_toBottomOf="@+id/post_str" />

    <TextView
        android:id="@+id/hasi3_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:fontFamily="@font/cafe24ssurround"
        android:text="#๊พธ์•ˆ๊พธ"
        android:layout_marginStart="15dp"
        android:textSize="15dp"
        app:layout_constraintStart_toEndOf="@+id/hasi2_text"
        app:layout_constraintTop_toBottomOf="@+id/post_str" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="25dp"
        android:background="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/hasi1_text" />

</androidx.constraintlayout.widget.ConstraintLayout>

๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ recycler view ์•„์ดํ…œ

์ด๋ฒˆ์—๋Š” ์˜ท๊ฑธ์ด(์ข‹์•„์š” ์นด์šดํŠธ), ๋ถ๋งˆํฌ ๊ธฐ๋Šฅ๋งŒ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ๋‹ค.

 

์›๋ž˜ ์žˆ๋˜ recyclerView Adapter ์ฝ”๋“œ์—์„œ

. . .
override fun onBindViewHolder(holder: MainPageFragmentRecyclerAdapter.CustomViewHolder, position: Int) {
	. . .
		// like ๋ฒ„ํŠผ ์ด๋ฒคํŠธ
        holder.like.setOnClickListener {
            favoriteEvent(position)
        }

        holder.bookMark.setOnClickListener {
            bookMarkEvent(position)
        }

        // like count, like image ์ด๋ฒคํŠธ
        // like๋ฅผ ํด๋ฆญํ•œ ๊ฒฝ์šฐ
        if (postDto[position].favorite.containsKey(uid)) {
            holder.like.setImageResource(R.drawable.hanger_selected)
        } else {    // like๋ฅผ ํด๋ฆญํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
            holder.like.setImageResource(R.drawable.hanger_unselected)
        }

        if (postDto[position].bookmark.containsKey(uid)) {
            holder.bookMark.setImageResource(R.drawable.tag_selected)
        } else {
            holder.bookMark.setImageResource(R.drawable.tag_unselected)
        }
	. . .
}

viewHolder ๋ถ€๋ถ„์— ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ์„ค์ •ํ•ด ์ค€๋‹ค.

ํด๋ฆญํ•˜๋ฉด ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์คฌ๋‹ค.

 

์ข‹์•„์š” ์นด์šดํŠธ ์„ธ๊ธฐ

private fun favoriteEvent(position: Int) {
    val tsDoc = fireStore.collection("posts").document(postUidList[position])
    fireStore.runTransaction { transition ->
        val postDto = transition.get(tsDoc).toObject(PostDto::class.java)

        // ์ข‹์•„์š”๊ฐ€ ๋ˆŒ๋ฆฐ ๊ฒฝ์šฐ
        if (postDto!!.favorite.containsKey(uid)) {
            postDto.favoriteCount -= 1
            postDto.favorite.remove(uid)
        } else {    // ๋ˆŒ๋ฆฌ์ง€ ์•Š์€ ๊ฒฝ์šฐ
            postDto.favoriteCount += 1
            postDto.favorite[uid!!] = true
        }

        transition.set(tsDoc, postDto)
    }
}

fireStore์—์„œ posts์˜ ํ•ด๋‹น๋˜๋Š” post์— ์ ‘๊ทผํ•ด

๋ˆ„๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ํ•ด๋‹น ์œ ์ €์˜ uid๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ true๋กœ ์ง€์ •ํ•ด ์ฃผ์—ˆ๊ณ ,

์ข‹์•„์š” ์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œ์ผฐ๋‹ค.

 

๋ถ๋งˆํฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ธฐ

private fun bookMarkEvent(position: Int) {
    val tsDoc = fireStore.collection("posts").document(postUidList[position])
    fireStore.runTransaction {
        val post = it.get(tsDoc).toObject(PostDto::class.java)

        if (post!!.bookmark.containsKey(uid)) {
            post.bookmark.remove(uid)
        } else {
            post.bookmark[uid!!] = true
        }

        it.set(tsDoc, post)
    }
}

fireStore์—์„œ posts์˜ ํ•ด๋‹น๋˜๋Š” post์— ์ ‘๊ทผํ•ด

๋ˆ„๊ฐ€ ๋ถ๋งˆํฌ๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ true๋กœ ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ–ˆ๋‹ค.


๊ฒฐ๊ณผ

์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅธ ํ™”๋ฉด

์ข‹์•„์š” ์ด๋ฏธ์ง€๊ฐ€ ์ž˜ ๋ณ€๊ฒฝ๋˜์—ˆ๊ณ , ์ข‹์•„์š” ์นด์šดํŠธ์™€ ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅธ ์œ ์ €์˜ uid๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋“ค์–ด์™”๋‹ค.

 

๋ถ๋งˆํฌ

๋ถ๋งˆํฌ ์ด๋ฏธ์ง€ ์ƒ‰ ๋ณ€๊ฒฝ๋„ ์ž˜ ๋˜์—ˆ๊ณ , ๋ˆ„๋ฅธ ์œ ์ €์˜ ์ •๋ณด๋„ ์ž˜ ๋“ค์–ด์™”๋‹ค.


๋‹ค์Œ ํฌ์ŠคํŒ…์—๋Š” ๋ถ๋งˆํฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ๋‹ค.

728x90