使用 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.
的官方文档
我正在 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.
的官方文档