使用 android 中的 recyclerview 按钮更新特定的 firebase 字段

Updating specific firebase field using recyclerview button in android

我正在 Java 中使用 Android Studio 开发一个投票应用程序,它使用 RecyclerView 列出 Firebase 数据库中的所有候选人。我能够列出所有候选人,但无法实现投票按钮以仅更新特定候选人的总票数。

RecyclerView中拾取数据显示如下: RecyclerView中的候选人信息:

我需要每次用户点击投票按钮时,数据库 totalVotes 字段都会更新 +1。

MyAdapter 代码:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    Context context;
    ArrayList <Candidate> candidates;
    private DatabaseReference mDatabase;


    public MyAdapter (Context c, ArrayList<Candidate> p){
        context = c;
        candidates =p;
    }


    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.cardview, parent, false));
    }
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.name.setText(candidates.get(position).getFirstname());
        holder.party.setText(candidates.get(position).getParty());
        holder.category.setText(candidates.get(position).getCategory());
        Picasso.get().load(candidates.get(position).getImageurl()).into(holder.profilepic);

        holder.onClick(position);
    }

    @Override
    public int getItemCount() {
        return candidates.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{

        TextView name, party, category;
        ImageView profilepic;
        Button vote;

        public MyViewHolder(View itemView) {
            super(itemView);
            name = (TextView) itemView.findViewById(R.id.name);
            party = (TextView) itemView.findViewById(R.id.party);
            profilepic = (ImageView) itemView.findViewById(R.id.profilepic);
            category = (TextView) itemView.findViewById(R.id.category);
            vote = (Button) itemView.findViewById(R.id.vote);
        }

        public void onClick(int position){
            vote.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
        }
    }


}

AllCandidates class 处理适配器:

private DatabaseReference reference;
    private RecyclerView recyclerView;
    private ArrayList<Candidate> list;
    private ArrayList<CandidateIMage> listimage;
    private MyAdapter adapter;
    private DatabaseReference imagereference;
    FirebaseStorage storage;
    StorageReference storageReference;

    private static final String TAG = "AllCandidates";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.all_candidates);

        //reference= FirebaseDatabase.getInstance().getReference().child("candidates");
        recyclerView = (RecyclerView) findViewById(R.id.myRecycler);

        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        list = new ArrayList<Candidate>();
        listimage = new ArrayList<CandidateIMage>();

        reference = FirebaseDatabase.getInstance().getReference();

        Query presidentquery = reference.child("candidates").orderByChild("category").equalTo("President");
        presidentquery.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if (dataSnapshot.exists()) {
                    for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                        Candidate p = dataSnapshot1.getValue(Candidate.class);
                        //String userId = dataSnapshot1.getKey();
                        //System.out.println("User id to be passed is: "+userId);
                        list.add(p);
                    }
                    adapter = new MyAdapter(AllCandidates.this, list);
                    recyclerView.setAdapter(adapter);
                }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
        };
    }

我曾尝试将此代码添加到 vote.onclicklostener 但它不起作用:

public void onClick(final int position){
            postRef = FirebaseDatabase.getInstance().getReference("candidates");
            vote.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    postRef.runTransaction(new Transaction.Handler() {
                        @Override
                        public Transaction.Result doTransaction(MutableData mutableData) {
                            Candidate p = mutableData.getValue(Candidate.class);
                            if (p == null) {
                                return Transaction.success(mutableData);
                            } else {
                                int fetched = p.getTotalVotes();
                                fetched = fetched + 1;

                                String userId = postRef.push().getKey();
                                // Set value and report transaction success
                                postRef.child(userId).child("totalVotes").setValue(fetched);

                                //mutableData.setValue(p);
                                return Transaction.success(mutableData);
                            }
                        }
                        @Override
                        public void onComplete(DatabaseError databaseError, boolean b,
                                               DataSnapshot dataSnapshot) {
                            // Transaction completed
                            Log.d(TAG, "postTransaction:onComplete:" + databaseError);
                        }
                    });
                }


            });
        }

我的候选人 m0del 看起来像这样:

@IgnoreExtraProperties
public class Candidate {
    private String firstname;
    private String lastname;
    private String party;
    private String category;
    private String candidateemail;
    private String imageurl;
    public Integer totalVotes;

    // Default constructor required for calls to
    // DataSnapshot.getValue(Candidate.class)
    public Candidate() {
    }

    public Candidate(String imageurl, String candidateemail, String firstname, String lastname, String party, String category, Integer totalVotes) {

        this.candidateemail = candidateemail;
        this.imageurl = imageurl;
        this.firstname = firstname;
        this.lastname = lastname;
        this.party = party;
        this.category = category;
        this.totalVotes = totalVotes;
    }

    public String getCandidateemail() {
        return candidateemail;
    }

    public void setCandidateemail(String candidateemail) {
        this.candidateemail = candidateemail;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getParty() {
        return party;
    }

    public void setParty(String party) {
        this.party = party;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public Integer getTotalVotes() {
        return totalVotes;
    }

    public void setTotalVotes(Integer totalVotes) {
        this.totalVotes = totalVotes;
    }

    public String getImageurl() {
        return imageurl;
    }

    public void setImageurl(String imageurl) {
        this.imageurl = imageurl;
    }

根据您的评论:

When I click on the vote button, it creates a new record in the database, instead of updating the totaLVotes field of the specific voted for a candidate.

发生这种情况是因为您以错误的方式使用交易。当您使用以下代码行时:

String userId = postRef.push().getKey();
postRef.child(userId).child("totalVotes").setValue(fetched);

由于每次调用 .push() 都会生成一个新的随机密钥,因此每次新的总计都会被推送到数据库中。只更新totalVotes属性,请使用以下方法:

public static void updateTotalVotes(String operation) {
    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference totalVotesRef = rootRef.child("candidates").child("-M35sglMi8onCgvEDzbm").child("totalVotes");
    totalVotesRef.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            Integer votes = mutableData.getValue(Integer.class);
            if (votes == null) {
                return Transaction.success(mutableData);
            }

            if (operation.equals("increaseTotalVotes")) {
                mutableData.setValue(votes + 1);
            } else if (operation.equals("decreaseTotalVotes")){
                mutableData.setValue(votes - 1);
            }

            return Transaction.success(mutableData);
        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
            Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
        }
    });
}

看,您必须设置使用指向 totalVotes 属性 的引用。现在开始:

updateTotalVotes("increaseTotalVotes");

有关详细信息,请查看关于 saving data as transactions.

的官方文档