Android Firestore将限制设置为每位用户1票

时间:2019-07-26 18:37:44

标签: android google-cloud-firestore android-togglebutton

我正在从头开始创建我的第一个应用程序,它是android上的一个论坛应用程序,我已经开始赞成/不赞成投票了。

我将其设置为我的用户可以在其中投票(与StackOverflow类似),但是我不知道如何将投票限制为每个用户一票。

我正在使用Firebase-Firestore作为数据库。

我将upvote和downvote切换按钮设置为在按钮单击侦听器中使用各自的选择器item.xml更新Firestore中的乐谱。

有人能阐明一种将用户限制为每个用户每个答案只能投票一次的方法吗?

感谢您的帮助。

  

编辑

尝试提供答案之前的当前代码。

AnswerAdapter

public class AnswerAdapter extends FirestoreRecyclerAdapter<Answer, AnswerAdapter.AnswerHolder> {

    private QuestionAdapter.OnItemClickListener listener;
    private Context mContext;
    private static final String TAG = "AnswerAdapter";

    /**
     * Create a new RecyclerView adapter that listens to a Firestore Query.  See {@link
     * FirestoreRecyclerOptions} for configuration options.
     *
     * @param options
     */

    public AnswerAdapter(@NonNull FirestoreRecyclerOptions<Answer> options) {

        super(options);
    }

    @NonNull
    @Override
    public AnswerHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.answer_item, viewGroup, false);
        return new AnswerHolder(v);
    }

    @Override
    protected void onBindViewHolder(@NonNull final AnswerAdapter.AnswerHolder answerHolder, final int position, @NonNull final Answer model) {

        answerHolder.answerItemTextView.setText(model.getAnswer());
        answerHolder.answerAuthorTextView.setText(model.getAuthor());
        answerHolder.answerTimeStampTextView.setText(model.getTimestamp());
        answerHolder.answerScoreTextView.setText(getSnapshots().getSnapshot(position).get("answerScore").toString());

        answerHolder.mAnswerUpVoteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO: 2019-07-26 check order of operations. seems to go through upvote and then also through downvote unchecking state
                if (answerHolder.mAnswerUpVoteButton.isChecked()){

                    answerUpVote(answerHolder, position, model);
                } else {
//                    answerDownVote(answerHolder, position, model);
                }
            }
        });

public class AnswerHolder extends RecyclerView.ViewHolder{

        TextView answerItemTextView;
        TextView answerScoreTextView;
        ToggleButton answerCheckMark;
        TextView answerAuthorTextView;
        TextView answerTimeStampTextView;
        ToggleButton mAnswerUpVoteButton;
        ToggleButton mAnswerDownVoteButton;


        public AnswerHolder(@NonNull final View itemView) {
            super(itemView);
            answerItemTextView = itemView.findViewById(R.id.answerItemTextViewId);
            answerScoreTextView = itemView.findViewById(R.id.questionScoreId);
            answerCheckMark = itemView.findViewById(R.id.answerCheckMarkId);
            answerAuthorTextView = itemView.findViewById(R.id.answerAuthorTextViewId);
            answerTimeStampTextView = itemView.findViewById(R.id.answerTimeStampTextViewId);
            mAnswerUpVoteButton = itemView.findViewById(R.id.answerUpVoteId);
            mAnswerDownVoteButton = itemView.findViewById(R.id.answerDownVoteId);

            mContext = itemView.getContext();

        }

    }

private void answerUpVote(@NonNull final AnswerAdapter.AnswerHolder answerHolder, final int position, @NonNull final Answer model) {
        final String answerScoreFBValue = getSnapshots().getSnapshot(position).get("answerScore").toString();
        final String answerFirebaseIdString = getSnapshots().getSnapshot(position).get("answerFirebaseId").toString();
//        Toast.makeText(mContext, "upvote button clicked " + answerScoreFBValue, Toast.LENGTH_SHORT).show();
        final CollectionReference answerCollectionRef = FirebaseFirestore.getInstance().collection("Answers");
        final DocumentReference answerDocRef = answerCollectionRef.document(answerFirebaseIdString);


        answerDocRef.update("answerScore", FieldValue.increment(1)).addOnSuccessListener(new OnSuccessListener<Void>() {
            //                answerRef.document().update("answerscore", answerScoreTestInt).addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Log.d(TAG, "onSuccess: answerScore incremented");
//                answerHolder.answerScoreTextView.setText("testing");

            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.e(TAG, "onFailure: answerScore was not incremented", e);
            }
        });
    }

Answer.java

package com.example.stairmaster.models;

public class Answer {

    private String answer;
    private String comment; 
    private String timestamp;
    private int answerScore;
    private String author;
    private String answerFirebaseId;
    private String parentQuestionId;


    public Answer(String answer, String timeStamp, String author, String parentQuestionId, int answerScore) {

        this.answer = answer;
        this.timestamp = timeStamp;
        this.answerScore = answerScore;
        this.author = author;
        this.parentQuestionId = parentQuestionId;
    }

    public Answer () {
        // public no-arg constructor needed
    }

    public String getAnswerFirebaseId() {
        return answerFirebaseId;
    }

    public void setAnswerFirebaseId(String answerFirebaseId) {
        this.answerFirebaseId = answerFirebaseId;
    }

    public String getAnswer() {
        return answer;
    }

    public void setAnswer(String answer) {
        this.answer = answer;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public int getAnswerScore() {
        return answerScore;
    }

    public void setAnswerScore(int answerScore) {
        answerScore = answerScore;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getParentQuestionId() {
        return parentQuestionId;
    }

    public void setParentQuestionId(String parentQuestionId) {
        this.parentQuestionId = parentQuestionId;
    }
}

2 个答案:

答案 0 :(得分:1)

我正在做类似的事情,而我的方法是使用本地会议室数据库。因此,首先,它检查本地数据库以查看用户是否可以投票。如果可以的话,它将向Firestore发送请求以更新关联的字段。我还使用RxKotlin,并将返回的Task <>(从请求到Firestore)包装到一个可观察对象中。如果观察到的内容没有任何错误地完成,那么它将更新本地数据库。如果失败,那么它什么都不做。我敢肯定还有其他方法,但这就是我选择的方式。

答案 1 :(得分:1)

您可能会考虑将Firebase数据库中的数据库表修改为如下所示。

user_votes:
  - userid: 1234232 // A sample user id for your user
    - forumid: 8769765 // The id of the forum or blog
      - upvote: 1 // Number of upvotes in that specific forum/blog
      - downvote: 0 // Number indicates the downvote to that forum/blog
    - forumid: 1233432 
      - upvote: 1 
      - downvote: 0 
    - forumid: 8712169767 
      - upvote: 0 
      - downvote: 1 

另一个用于保存特定论坛/博客的赞成/反对票记录的表可能如下所示。

all_votes:
  - forumid: 8769765 // The id of the forum or blog
    - upvote: 9876 // Number of upvotes in that specific forum/blog
    - downvote: 123 // Number indicates the downvote to that forum/blog
  - forumid: 1233432 
    - upvote: 87 
    - downvote: 12 
  - forumid: 8712169767 
    - upvote: 112 
    - downvote: 10

现在,基于这两个表,您可以轻松决定是否要在setValue表中发出all_votes命令以获取论坛ID。如果发现用户已经发出过赞,则以这样的方式进行应用程序逻辑:它不会在all_votes表中为该特定用户发出过一次过赞。

希望有帮助!