I'm developing a voting app using Android Studio in Java that uses RecyclerView to list all candidates from the Firebase database. I'm able to list all candidates, but can't implement the vote button to only update a specific candidate's total votes.
The data is picked and displayed in a RecyclerView as follows:
Candidates information in RecyclerView:
I need each time a user clicks on the vote button, the database totalVotes field is updated with a +1.
MyAdapter code:
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 that handles the adapter:
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) {
}
});
};
}
I had tried to add this code to the vote.onclicklostener but it is not working:
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);
}
});
}
});
}
My Candidate m0del looks like this:
#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;
}
According to your comment:
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.
This is happening because you are using the transaction in the wrong way. When you are using the following lines of code:
String userId = postRef.push().getKey();
postRef.child(userId).child("totalVotes").setValue(fetched);
You are pushing in the database every time a new total since the call to the .push() generates a new random key each time is called. To update only the totalVotes property, please use the following method:
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!
}
});
}
See, you have to set use a reference that points to the totalVotes property. Now kick it off with:
updateTotalVotes("increaseTotalVotes");
For more information please check the official documentation regarding saving data as transactions.
Related
I get this error when I run the program:
com.cdirect.agenda2.AllEvents$1.onDataChange(AllEvents.java:47)
-Events events = dataSnapshot.getValue(Events.class);
I want to get all data from my FirebaseDatabase. I created Events.java. It has getter and setters. MyAdapter is adapting for RecyclerView on AllEvents.java. I want to show all data on AllEvents.java.
But I cannot success. Can you help me?
MyAdapter.java:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
Context context;
ArrayList<Events> list;
public MyAdapter(Context context, ArrayList<Events> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.evententry,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Events events = list.get(position);
holder.plan.setText(events.getPlan());
holder.note.setText(events.getNote());
holder.date.setText(events.getDate());
holder.time.setText(events.getTime());
holder.remb.setText(events.getRemb());
}
#Override
public int getItemCount() {
return list.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
TextView id, plan, note, date, time, remb;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
id = itemView.findViewById(R.id.tvIdCard);
plan = itemView.findViewById(R.id.tvPlanCard);
note = itemView.findViewById(R.id.tvNoteCard);
date = itemView.findViewById(R.id.tvDateCard);
time = itemView.findViewById(R.id.tvTimeCard);
remb = itemView.findViewById(R.id.tvRememberCard);
}
}
MyEvents.java
public class AllEvents extends AppCompatActivity {
RecyclerView recyclerView;
ArrayList<Events> list;
DatabaseReference dbRef;
MyAdapter adapter;
#Override
public void onBackPressed() {
super.onBackPressed();
startActivity(new Intent(AllEvents.this, MainActivity.class));
finish();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_events);
recyclerView = findViewById(R.id.recycleView);
dbRef = FirebaseDatabase.getInstance().getReference("Events");
list = new ArrayList<>();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyAdapter(this, list);
recyclerView.setAdapter(adapter);
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot: snapshot.getChildren()){
Events events = dataSnapshot.getValue(Events.class);
list.add(events);
}
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
}
Events.java
public class Events {
String id;
String plan;
String note;
String date;
String time;
String remb;
public Events(String id, String plan, String note, String date, String time, String remb) {
this.id = id;
this.plan = plan;
this.note = note;
this.date = date;
this.time = time;
this.remb = remb;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPlan() {
return plan;
}
public void setPlan(String plan) {
this.plan = plan;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getRemb() {
return remb;
}
public void setRemb(String remb) {
this.remb = remb;
}
}
My Database is:
enter image description here
First try to make them private for the Event class.
private String id;
private String plan;
private String note;
private String date;
private String time;
private String remb;
Second, change adapter = new MyAdapter(this, list); line to here. Additional here, you need handle whenonCancelled also.
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot: snapshot.getChildren()){
Events events = dataSnapshot.getValue(Events.class);
list.add(events);
}
adapter = new MyAdapter(this, list);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.i("???", "onCancelled Error: " + error.getMessage());
}
});
I'm referring this tutorial ==> https://uniqueandrocode.com/add-to-favourites-and-display-favourites-in-recyclerview/ in my project I have bottom navigation...I am trying to add favourites in the first tab and displaying favourites in the second tab in the bottom navigation bar. I'm using Room library.
When activity loads favourites are all blank at first, but when I first row as favourite and go-to favourite tab it displays properly but when I came back to the first tab it fills all the favourites icon automatically (which I have not done I had only done the first row)
Really need help. Thanks in advance.
Dao:
#Dao
public interface FavoriteDao {
#Insert
public void addData(FavoriteList favoriteList);
#Query("select * from favoritelist")
public List<FavoriteList> getFavoriteData();
#Query("SELECT EXISTS (SELECT 1 FROM favoritelist WHERE id=:id)")
public int isFavorite(int id);
#Delete
public void delete(FavoriteList favoriteList);
}
Database:
#Database(entities={FavoriteList.class},version = 1)
public abstract class FavoriteDatabase extends RoomDatabase {
public abstract FavoriteDao favoriteDao();
}
FavoriteList:
#Entity(tableName="favoritelist")
public class FavoriteList {
#PrimaryKey
private int id;
#ColumnInfo(name = "source")
private String source;
#ColumnInfo(name = "author")
private String author;
#ColumnInfo(name = "title")
private String title;
#ColumnInfo(name = "description")
private String description;
#ColumnInfo(name = "url")
private String url;
#ColumnInfo(name = "urlToImage")
private String urlToImage;
#ColumnInfo(name = "publishedAt")
private String publishedAt;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUrlToImage() {
return urlToImage;
}
public void setUrlToImage(String urlToImage) {
this.urlToImage = urlToImage;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
}
News fragment:
public class news extends Fragment {
ImageView favbtn;
RecyclerView recyclerView;
SwipeRefreshLayout swipeRefreshLayout;
EditText etQuery;
Button btnSearch;
Adapter adapter;
List<Articles> articles = new ArrayList<>();
public static FavoriteDatabase favoriteDatabase;
public news() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_news, container, false);
swipeRefreshLayout = view.findViewById(R.id.swiprefresh);
etQuery = view.findViewById(R.id.etQuery);
btnSearch = view.findViewById(R.id.btnSearch);
favoriteDatabase= Room.databaseBuilder(getActivity(),FavoriteDatabase.class,"myfavdb").
allowMainThreadQueries().build();
recyclerView = view.findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
final String country = getCountry();
retrieveJson("", country, API_Key);
btnSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!etQuery.getText().toString().equals("")) {
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
retrieveJson(etQuery.getText().toString(), country, API_Key);
}
});
retrieveJson(etQuery.getText().toString(), country, API_Key);
} else {
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
retrieveJson("", country, API_Key);
}
});
retrieveJson("", country, API_Key);
}
}
});
return view;
}
private void showChangeLanguageDialog() {
}
public void retrieveJson(String query, String country, String apiKey) {
swipeRefreshLayout.setRefreshing(true);
Call<Headlines> call;
if (!etQuery.getText().toString().equals("")) {
call = ApiClient.getInstance().getApi().getSpecifiedData(query, apiKey);
} else {
call = ApiClient.getInstance().getApi().getHeadLines(country, apiKey);
}
call.enqueue(new Callback<Headlines>() {
#Override
public void onResponse(Call<Headlines> call, Response<Headlines> response) {
if (response.isSuccessful() && response.body().getArticles() != null) {
swipeRefreshLayout.setRefreshing(false);
// articles.clear();
articles = response.body().getArticles();
adapter = new Adapter(getContext(), articles);
recyclerView.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<Headlines> call, Throwable t) {
swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public String getCountry() {
Locale locale = Locale.getDefault();
String country = locale.getCountry();
return country.toLowerCase();
}
}
Adapter:
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
Context context;
List<Articles> articles;
public Adapter(Context context, List<Articles> articles) {
this.context = context;
this.articles = articles;
}
#NonNull
#Override
public Adapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final Adapter.ViewHolder holder, final int position) {
final Articles a = articles.get(position);
String imageUrl = a.getUrlToImage();
String url = a.getUrl();
holder.tvTitle.setText(a.getTitle());
Picasso.get().load(imageUrl).into(holder.imageView);
holder.tvSource.setText(a.getSource().getName());
holder.tvDate.setText(dateTime(a.getPublishedAt()));
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context,DetailedActivity.class);
intent.putExtra("title",a.getTitle());
intent.putExtra("source",a.getSource().getName());
intent.putExtra("time",dateTime(a.getPublishedAt()));
intent.putExtra("desc",a.getDescription());
intent.putExtra("imageUrl",a.getUrlToImage());
intent.putExtra("url",a.getUrl());
context.startActivity(intent);
}
});
if (news.favoriteDatabase.favoriteDao().isFavorite(articles.get(position).getId())==1)
holder.bookmark.setImageResource(R.drawable.ic_bookmark);
else
holder.bookmark.setImageResource(R.drawable.ic_baseline_bookmark_border_24);
holder.bookmark.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FavoriteList favoriteList = new FavoriteList();
int id = articles.get(position).getId();
String source = articles.get(position).getSource().getName();
String author = articles.get(position).getAuthor();
String publishedAt = articles.get(position).getPublishedAt();
String description = articles.get(position).getDescription();
String title = articles.get(position).getTitle();
String url = articles.get(position).getUrl();
String urlToImage = articles.get(position).getUrlToImage();
favoriteList.setId(id);
favoriteList.setAuthor(author);
favoriteList.setDescription(description);
favoriteList.setSource(source);
favoriteList.setPublishedAt(publishedAt);
favoriteList.setTitle(title);
favoriteList.setUrl(url);
favoriteList.setUrlToImage(urlToImage);
favoriteList.setPublishedAt(dateTime(articles.get(position).getPublishedAt()));
if (news.favoriteDatabase.favoriteDao().isFavorite(id)!=1){
holder.bookmark.setImageResource(R.drawable.ic_bookmark);
news.favoriteDatabase.favoriteDao().addData(favoriteList);
}else {
holder.bookmark.setImageResource(R.drawable.ic_baseline_bookmark_border_24);
news.favoriteDatabase.favoriteDao().delete(favoriteList);
}
}
});
}
#Override
public int getItemCount() {
return articles.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle, tvSource, tvDate;
ImageView imageView;
ImageButton bookmark;
CardView cardView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.tvId);
tvSource = itemView.findViewById(R.id.tvSource);
tvDate = itemView.findViewById(R.id.tvDate);
imageView = itemView.findViewById(R.id.image);
cardView = itemView.findViewById(R.id.cardView);
bookmark = itemView.findViewById(R.id.favrr);
}
}
Steps to debug:
Add 2-3 items as Favs.
Restart the Application.
Check if it shows those items as fav after restarting application .
also add logs to those if conditions where you are changing the drawables.
After looking at your JSON it looks like id is what creating problems. Id is null for all your json items so when fav. one it shows fav. to all.
Solution : Use another field to check if the data is added to fav.list
Delete will not work either
Try
#Query("DELETE FROM favoritelist WHERE title = :title")
void deleteByUserId(String title);
To delete item
Also https://github.com/amitshekhariitbhu/Android-Debug-Database
check this library to debug your database
I have a app with chatrooms where I want to show the people in that chatroom.When someone joins the chatroom I set the value of their node to be true.Like this
Like you can see I also have the data of users underit.I want to use the list of members/documentid and use that list to get the data of only those people from the profiledata node.
My class
public class chatroommembers extends AppCompatActivity {
String documentid;
RecyclerView recyclerView;
DatabaseReference peopleref;
DatabaseReference membersref;
private List<User> list;
private MembersAdapter membersAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chatroommembers);
Intent data = getIntent();
documentid = data.getStringExtra("documentid");
peopleref = FirebaseDatabase.getInstance().getReference().child("Users").child("profiledata");
membersref = FirebaseDatabase.getInstance().getReference().child("Chatrooms").child("members").child(documentid);
recyclerView = findViewById(R.id.membersRecycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
list = new ArrayList<>();
membersref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot snapshot1:snapshot.getChildren()){
String uid = snapshot1.getKey();
DatabaseReference peoplesref = peopleref.child(uid);
}
membersAdapter = new MembersAdapter(list);
recyclerView.setAdapter(membersAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
public static class User{
String fullname,imageUrl,Uid,Email,Buddies;
public String getFullname() {
return fullname;
}
public User(){
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getUid() {
return Uid;
}
public void setUid(String uid) {
Uid = uid;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getBuddies() {
return Buddies;
}
public void setBuddies(String buddies) {
Buddies = buddies;
}
public User(String fullname, String imageUrl, String uid, String email, String buddies) {
this.fullname = fullname;
this.imageUrl = imageUrl;
Uid = uid;
Email = email;
Buddies = buddies;
}
}
public class MembersAdapter extends RecyclerView.Adapter<MembersAdapter.MembersViewHolder>{
private List<User> list;
public MembersAdapter(List<User> list) {
this.list = list;
}
#NonNull
#Override
public MembersAdapter.MembersViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.users_recycler_layout,parent,false);
return new MembersAdapter.MembersViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MembersAdapter.MembersViewHolder holder, int position) {
User ld = list.get(position);
holder.name.setText(ld.getFullname());
if (ld.getImageUrl().equals("noimage")){
Glide.with(getApplicationContext()).load(R.drawable.profile).into(holder.circleImageView);
}else{
Glide.with(getApplicationContext()).load(ld.getImageUrl()).into(holder.circleImageView);
}
}
#Override
public int getItemCount() {
return list.size();
}
public class MembersViewHolder extends RecyclerView.ViewHolder{
TextView name;
CircleImageView circleImageView;
public MembersViewHolder(#NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.usersname);
circleImageView = itemView.findViewById(R.id.usersimage);
}
}
}
}
What you're describing is a fairly standard operation known as a client-side join. In Android it'd look something like this:
String chatroomId = "-MBISFO12u2tok9CeWwi";
DatabaseReference membersRef = FirebaseDatabase.getInstance().getReference("Chatrooms/members").child(chatroomId);
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("Users/profiledata")
membersRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot memberSnapshot: dataSnapshot.getChildren()) {
String uid = memberSnapshot.getKey();
DatabaseReference userRef = usersRef.child(uid);
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot userSnapshot) {
Log.i("USER", userSnapshot.child("Full name").getValue(String.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
I am developing an android application based on Rest Api remote data, in which I have made one RecyclerView. I have added 2 buttons with each row in RecyclerView. These 2 buttons are Accept and Decline. When user selects accept button certain portion of the JSON Property have to change to True and if selects decline button certain portion of the JSON Property have to change to false and #POST it. How can I do it?
I’m new in Rest Api with RecyclerView, so if you know the solution please help, thanks.
What i have been done so far:
My main activity:
public class ViewRefundRequest extends AppCompatActivity{
private RecyclerView viewRefundRequestRecylcerView;
private RecyclerView.LayoutManager layoutManager;
private AdminViewRefundRequestAdapter adapter;
List<ViewRefundRequestModel> vrrList;
RelativeLayout vrrMainLayout;
AdminViewRefundRequestAdapter.RecyclerViewClickListener listener;
ProgressBar progressBarVRR;
ApiService serviceVRR;
TokenManager tokenManagerVrr;
Call<List<ViewRefundRequestModel>> callViewRefundRequestData;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_refund_request);
tokenManagerVrr = TokenManager.getInstance(getSharedPreferences("prefs", MODE_PRIVATE));
serviceVRR = RetrofitBuilder.createServiceWithAuth(ApiService.class, tokenManagerVrr);
progressBarVRR = (ProgressBar) findViewById(R.id.viewRefundRequestProgressBar);
viewRefundRequestRecylcerView = (RecyclerView) findViewById(R.id.viewRefundRequestRecylcerView);
layoutManager = new LinearLayoutManager(this);
viewRefundRequestRecylcerView.setLayoutManager(layoutManager);
listener = new AdminViewRefundRequestAdapter.RecyclerViewClickListener() {
#Override
public void onRowClick(View view, int position) {
}
#Override
public void onButtonYesClick(View view, int position) {
int acceptStatusCode = 110;
final int id = vrrList.get(position).getId();
//final int statusCode = vrrList.get(position).getRefundStatus();
acceptRequest(id, acceptStatusCode);
adapter.notifyDataSetChanged();
}
#Override
public void onButtonNoClick(View view, int position) {
}
};
//Rest Api call
allViewRefundRequestData();
}
private void allViewRefundRequestData() {
progressBarVRR.setVisibility(View.VISIBLE);
callViewRefundRequestData = serviceVRR.getAllViewRefundRequest();
callViewRefundRequestData.enqueue(new Callback<List<ViewRefundRequestModel>>() {
#Override
public void onResponse(#NotNull Call<List<ViewRefundRequestModel>> call, #NotNull Response<List<ViewRefundRequestModel>> response) {
progressBarVRR.setVisibility(View.GONE);
if (response.isSuccessful() && response.body() != null){
vrrList = response.body();
adapter = new AdminViewRefundRequestAdapter(vrrList, ViewRefundRequest.this, listener);
viewRefundRequestRecylcerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}else {
if (response.code() == 401) {
startActivity(new Intent(ViewRefundRequest.this, LoginActivity.class));
finish();
tokenManagerVrr.deleteToken();
Toast.makeText(ViewRefundRequest.this, "User session expired, Login again", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onFailure(#NotNull Call<List<ViewRefundRequestModel>> call, #NotNull Throwable t) {
progressBarVRR.setVisibility(View.GONE);
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Network Status: " + t.getMessage(), Snackbar.LENGTH_LONG);
View snackbarView = snackbar.getView();
snackbarView.setBackgroundColor(Color.parseColor("#f5003d"));
TextView tv = (TextView) snackbarView.findViewById(R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
snackbar.show();
}
});
}
public void acceptRequest(final int id, final int statusCode){
Call<ViewRefundRequestModel> callAccepted = serviceVRR.acceptRefundRequest(id, statusCode);
callAccepted.enqueue(new Callback<ViewRefundRequestModel>() {
#Override
public void onResponse(Call<ViewRefundRequestModel> call, Response<ViewRefundRequestModel> response) {
Snackbar snackbar = Snackbar.make(vrrMainLayout, "Accepted", Snackbar.LENGTH_SHORT);
View snackbarView = snackbar.getView();
snackbarView.setBackgroundColor(Color.parseColor("#5ec639"));
TextView tv = (TextView) snackbarView.findViewById(R.id.snackbar_text);
tv.setTextSize(16);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setTypeface(tv.getTypeface(), Typeface.BOLD);
tv.setTextColor(Color.WHITE);
snackbar.show();
}
#Override
public void onFailure(Call<ViewRefundRequestModel> call, Throwable t) {
}
});
}
public void declineRequest(final int id, Integer statusCode, String noteRefund){
Call<ViewRefundRequestModel> callDeclined = serviceVRR.cancelRefundRequest(id, statusCode, noteRefund);
callDeclined.enqueue(new Callback<ViewRefundRequestModel>() {
#Override
public void onResponse(Call<ViewRefundRequestModel> call, Response<ViewRefundRequestModel> response) {
}
#Override
public void onFailure(Call<ViewRefundRequestModel> call, Throwable t) {
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
if (callViewRefundRequestData != null) {
callViewRefundRequestData.cancel();
callViewRefundRequestData = null;
}
}
}
My adapter class:
public class AdminViewRefundRequestAdapter extends BaseAdapter {
private List<ViewRefundRequestModel> viewRefundRequestModels;
List<ViewRefundRequestModel> viewRefundRequestModels;
private Context context;
private RecyclerViewClickListener mListener;
public AdminViewRefundRequestAdapter(List<ViewRefundRequestModel> viewRefundRequestModels, Context context, RecyclerViewClickListener listener) {
this.viewRefundRequestModels = viewRefundRequestModels;
this.context = context;
this.mListener = listener;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.model_view_refund_reques, parent, false);
return new MyViewHolder(view, mListener);
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
final ViewRefundRequestModel thisModelResponse = viewRefundRequestModels.get(position);
Patient patient = thisModelResponse.getPatient();
String patientName= patient.getFirstName()+" "+patient.getLastName();
Item item =thisModelResponse.getItem();
String itemName= item.getName();
ItemCategory itemCategory = item.getItemCategory();
String itemCategoryName = itemCategory.getName();
holder.patient_name.setText(patientName);
holder.patient_id.setText(Integer.toString(thisModelResponse.getPatientID()));
holder.item_name.setText(itemName);
holder.category.setText(itemCategoryName);
holder.quantity.setText(Integer.toString(thisModelResponse.getServiceQuantity()));
holder.amount.setText(Double.toString(thisModelResponse.getServiceActualPrice()));
holder.discount.setText(Double.toString(thisModelResponse.getDiscount()));
holder.amount_after_discount.setText(Double.toString(thisModelResponse.getServiceListPrice()));
holder.refund_note.setText(thisModelResponse.getRefundNote());
}
#Override
public int getItemCount() {
return viewRefundRequestModels.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private RecyclerViewClickListener mListener;
private TextView patient_name, patient_id, item_name,
category, quantity, amount, discount, amount_after_discount, refund_note;
private Button make_decisionBtn_Yes, make_decisionBtn_No;
private RelativeLayout row_container_vrr;
public MyViewHolder(#NonNull View itemView, RecyclerViewClickListener listener) {
super(itemView);
patient_name = itemView.findViewById(R.id.patient_name_VRR_Model);
patient_id = itemView.findViewById(R.id.patient_id_VRR_Model);
item_name = itemView.findViewById(R.id.item_name_VRR_Model);
category = itemView.findViewById(R.id.category_VRR_Model);
quantity = itemView.findViewById(R.id.quantity_VRR_Model);
amount = itemView.findViewById(R.id.amount_VRR_Model);
discount = itemView.findViewById(R.id.discount_VRR_Model);
amount_after_discount = itemView.findViewById(R.id.amount_after_discount_VRR_Model);
refund_note = itemView.findViewById(R.id.refund_note_VRR_Model);
make_decisionBtn_Yes = itemView.findViewById(R.id.make_decisionBtn01_VRR_Model);
make_decisionBtn_No = itemView.findViewById(R.id.make_decisionBtn02_VRR_Model);
row_container_vrr = itemView.findViewById(R.id.row_container_vrr);
mListener = listener;
row_container_vrr.setOnClickListener(this);
make_decisionBtn_Yes.setOnClickListener(this);
make_decisionBtn_No.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.row_container_vrr:
mListener.onRowClick(row_container_vrr, getAdapterPosition());
break;
case R.id.make_decisionBtn01_VRR_Model:
mListener.onButtonYesClick(make_decisionBtn_Yes, getAdapterPosition());
break;
case R.id.make_decisionBtn02_VRR_Model:
mListener.onButtonNoClick(make_decisionBtn_No, getAdapterPosition());
break;
default:
break;
}
}
}
public interface RecyclerViewClickListener {
void onRowClick(View view, int position);
void onButtonYesClick(View view, int position);
void onButtonNoClick(View view, int position);
}
}
Where did I go wrong?
Or should I follow another approach?
If I have to then what is it?
You can do like this first create a Pojo class like
class SendDataModel{
private String email;
private Name name;
private String password;
public String getEmail ()
{
return email;
}
public void setEmail (String email)
{
this.email = email;
}
public Name getName ()
{
return name;
}
public void setName (Name name)
{
this.name = name;
}
public String getPassword ()
{
return password;
}
public void setPassword (String password)
{
this.password = password;
}
#Override
public String toString()
{
return "ClassPojo [email = "+email+", name = "+name+", password = "+password+"]";
}
}
and other Pojo Class like
class Name{
private String lastName;
private String firstName;
public String getLastName ()
{
return lastName;
}
public void setLastName (String lastName)
{
this.lastName = lastName;
}
public String getFirstName ()
{
return firstName;
}
public void setFirstName (String firstName)
{
this.firstName = firstName;
}
#Override
public String toString()
{
return "ClassPojo [lastName = "+lastName+", firstName = "+firstName+"]";
}
}
and set your first and last name like
Name name = new Name();
name.setFirstName();
name.setLastName();
SendDataModel sendDatamodel=new SendDataModel();
sendDatamodel.setName(name);
sendDatamodel.setEmail("yourEmail")
sendDatamodel.setPassword("yourPassword");
and pass your sendDatamodel to your request.
Call<RegisterResponseModel> res = apiService.register(sendDatamodel);
res.enqueue(new Callback<RegisterResponseModel>() {
#Override
public void onResponse(Call<RegisterResponseModel> call,
Response<RegisterResponseModel> response) {
}
#Override
public void onFailure(Call<RegisterResponseModel> call, Throwable t)
{
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
you have to set clickListener in onBindViewHolder like
#Override public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
...
holder.row_container_vrr.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
mListener.onRowClick(v, position);
}
);
holder.make_decisionBtn_Yes.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
mListener.onButtonYesClick(v, position);
}
);
holder.make_decisionBtn_No.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
mListener.onButtonNoClick(v, position);
}
);
}
My RecyclerView not show any data from Firebase. I don't see any errors at logcat so I don't know why. I followed guide from youtube video. But still nothing. I'm using android 8.0 and API 27. Hope Somebody can help.
My Main Activity Code:
public class ViewProduct extends AppCompatActivity {
DatabaseReference ref;
ArrayList<Model> list;
private RecyclerView recyclerView;
private RecyclerView.Adapter viewHolder;
private RecyclerView.LayoutManager layoutManager;
SearchView searchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_product) ;
ref = FirebaseDatabase.getInstance().getReference().child("buddymealplanneruser").
child("Products");
recyclerView = findViewById(R.id.stallproductRecyclerView);
//recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//SEARCH VIEW
searchView = findViewById(R.id.searchProductStall);
//ADAPTER
list = new ArrayList<>();
viewHolder = new ViewHolder(list);
recyclerView.setAdapter(viewHolder);
}
#Override
protected void onRestart() {
super.onRestart();
if (ref!=null)
{
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists())
{
//list = new ArrayList<>();
list.clear();
for(DataSnapshot ds : dataSnapshot.getChildren())
{
list.add(ds.getValue(Model.class));
}
//ViewHolder viewHolder = new ViewHolder(list);
//recyclerView.setAdapter(viewHolder);
viewHolder.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(ViewProduct.this, databaseError.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
}
if (searchView !=null)
{
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s) {
search(s);
return true;
}
});
}
}
private void search(String str) {
ArrayList<Model> myList = new ArrayList<>();
for(Model object : list)
{
if(object.getProductName().toLowerCase().contains(str.toLowerCase()))
{
myList.add(object);
}
}
ViewHolder viewHolder = new ViewHolder(myList);
recyclerView.setAdapter(viewHolder);
}
}
My Adapter:
public class ViewHolder extends RecyclerView.Adapter<ViewHolder.MyViewHolder> {
ArrayList<Model> list;
public ViewHolder (ArrayList<Model> list)
{
this.list=list;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_product, viewGroup,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.productName.setText(list.get(i).getProductName());
myViewHolder.productCalorie.setText(list.get(i).getProductCalorie());
myViewHolder.StallId.setText(list.get(i).getStallId());
myViewHolder.productType.setText(list.get(i).getProductType());
myViewHolder.productServing.setText(list.get(i).getProductServing());
myViewHolder.statusProduct.setText(list.get(i).getStatusProduct());
}
#Override
public int getItemCount()
{
return list.size();
}
class MyViewHolder extends RecyclerView.ViewHolder
{
TextView productName, productCalorie, StallId;
TextView productType, productServing, statusProduct;
ImageView productImageView;
public MyViewHolder (#NonNull View itemView){
super((itemView));
productName = itemView.findViewById(R.id.productTitle);
productCalorie = itemView.findViewById(R.id.productDescriptionCalorie);
StallId = itemView.findViewById(R.id.productDescriptionStallId);
productType = itemView.findViewById(R.id.productDescriptionType);
productServing=itemView.findViewById(R.id.productDescriptionServing);
statusProduct=itemView.findViewById(R.id.productDescriptionAvailibility);
//productImageView = itemView.findViewById(R.id.productImageView);
}
}
}
My Model :
package com.example.buddymealplannerstall.Child;
import android.view.Display;
public class Model {
//String productName, productImage, productCalorie, StallId, productType, productServing, statusProduct;
private String StallId;
private String productCalorie;
private String productImage;
private String productName;
private String productServing;
private String productType;
private String statusProduct;
public Model (String StallId,
String productCalorie,
String productImage,
String productName,
String productServing,
String productType,
String statusProduct){
this.StallId = StallId;
this.productCalorie = productCalorie;
this.productImage = productImage;
this.productName = productName;
this.productServing = productServing;
this.productType = productType;
this.statusProduct = statusProduct;
}
public Model(){
}
public String getStallId() {
return StallId;
}
public void setStallId(String stallId) {
StallId = stallId;
}
public String getProductCalorie() {
return productCalorie;
}
public void setProductCalorie(String productCalorie) {
this.productCalorie = productCalorie;
}
public String getProductImage() {
return productImage;
}
public void setProductImage(String productImage) {
this.productImage = productImage;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductServing() {
return productServing;
}
public void setProductServing(String productServing) {
this.productServing = productServing;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public String getStatusProduct() {
return statusProduct;
}
public void setStatusProduct(String statusProduct) {
this.statusProduct = statusProduct;
}
}
Screen Shot of my firebase and my apps.
firebase
my app
According to your comment:
yes, buddymealplanner is my project's name
Please note that there is no need to add the name of your project as a child in the reference. So please change the following line of code:
ref = FirebaseDatabase.getInstance().getReference().child("buddymealplanneruser").
child("Products");
Simply to:
ref = FirebaseDatabase.getInstance().getReference().child("Products");
I dont think you are populating your list, you are sending it empty. From what I can see, you only add items to the list when you are restarting the activity. Try either populating it before sendinig the list, or changing the onRestart() for an onStart() or an onResume().