본문 바로가기
Front-end/Android (안드로이드 앱 개발)

Android Studio , Firebase 파이어베이스 : 실시간 데이터베이스 트랜잭션 (Transaction), 좋아요 구현

by javapp 자바앱 2021. 1. 18.
728x90

시나리오

좋아요 버튼을 누른다

트랜잭션으로 실시간데이터베이스에 저장

 

 

데이터 트랜잭션으로 저장은 (좋아요) 증가 감소 카운터와 같이 동시 수정으로 동기화가 필요한 데이터를 다루는 경우

트랜잭션 작업을 사용

ex) 게시글에 별표주기, 게시글 별표 몇 개 받았는지 

 

<기본 코드>

private void onStarClicked(DatabaseReference postRef) {
    postRef.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            Post p = mutableData.getValue(Post.class);
            if (p == null) {
                return Transaction.success(mutableData);
            }

            if (p.stars.containsKey(getUid())) {
                // Unstar the post and remove self from stars
                p.starCount = p.starCount - 1;
                p.stars.remove(getUid());
            } else {
                // Star the post and add self to stars
                p.starCount = p.starCount + 1;
                p.stars.put(getUid(), true);
            }

            // Set value and report transaction success
            mutableData.setValue(p);
            return Transaction.success(mutableData);
        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean committed,
                               DataSnapshot currentData) {
            // Transaction completed
            Log.d(TAG, "postTransaction:onComplete:" + databaseError);
        }
    });
}

 

 


프로젝트 적용하기

 

1.

DTO에 카운터와 좋아요유무(map) 추가한다.

 

public class ImageDTO
{
    private int startCount = 0;
    private Map<String, Boolean> stars = new HashMap<>();
    
    /...
 }

 

2.

   private FirebaseAuth mAuth;
   private FirebaseDatabase firebaseDatabase;
    
        mAuth = FirebaseAuth.getInstance();
        firebaseDatabase = FirebaseDatabase.getInstance();

 

3.

트랜잭션 저장 함수

    //좋아요 데이터베이스 트랜잭션 저장
    private void onStarClicked(DatabaseReference postRef) {
        postRef.runTransaction(new Transaction.Handler() {
            @Override
            public Transaction.Result doTransaction(MutableData mutableData) {
                ImageDTO imageDTO = mutableData.getValue(ImageDTO.class);
                if (imageDTO == null) {
                    return Transaction.success(mutableData);
                }

                //좋아요 누른 사람을 확인
                if (imageDTO.getStars().containsKey(mAuth.getCurrentUser().getUid()))
                {
                    // Unstar the post and remove self from stars
                    //좋아요 취소
                    imageDTO.setStartCount(imageDTO.getStartCount() - 1);
                    imageDTO.getStars().remove(mAuth.getCurrentUser().getUid());
                } else {
                    // Star the post and add self to stars
                    //좋아요 증가
                    imageDTO.setStartCount(imageDTO.getStartCount() + 1);
                    imageDTO.getStars().put(mAuth.getCurrentUser().getUid(), true);
                }

                // Set value and report transaction success
                mutableData.setValue(imageDTO);
                return Transaction.success(mutableData);
            }

            @Override
            public void onComplete(DatabaseError databaseError, boolean committed,
                                   DataSnapshot currentData) {
                // Transaction completed
            }
        });
    }

 

4.

리싸이클러뷰에 적용

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position)
    {
        holder.textViewUser.setText(imageDTOList.get(position).getUserId());
        holder.textViewTitle.setText(imageDTOList.get(position).getTitle());
        holder.textViewDesc.setText(imageDTOList.get(position).getDescription());
        holder.textViewCount.setText(Integer.toString(imageDTOList.get(position).getStartCount()));

        context = holder.itemView.getContext();
        String url = imageDTOList.get(position).getImageUrl();
        Glide.with(context)
                .load(url)
                .placeholder(R.drawable.g3)
                .into(holder.imageView);

        //하트 누른 상태이면
        if (imageDTOList.get(position).getStars().containsKey(mAuth.getCurrentUser().getUid())) {
            holder.imageViewHeart.setImageResource(R.drawable.favorite_black_24dp);
        }else {
            holder.imageViewHeart.setImageResource(R.drawable.favorite_border_black_24dp);
        }

        holder.imageViewHeart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //데이터베이스 위치, images/하나의 게시물 key/starts,startCount ..
                onStarClicked(firebaseDatabase.getReference().child("Profile").child(uidList.get(position)));
            }
        });
    }

 

//데이터베이스 위치, images/하나의 게시물 key/starts,startCount ..
onStarClicked(firebaseDatabase.getReference().child("Profile").child(uidList.get(position)));

 

 

//좋아요 데이터베이스 트랜잭션 저장
private void onStarClicked(DatabaseReference postRef) { //postRef == uidList.get(position) == MPxBu8Ndca_...

/...

}

stars는 map 컬렉션으로 좋아요 누른 유저 uid와 boolean 값을 저장

 

 

댓글