I'm using Firebase with RecyclerView,I'd like to retrieve the child with a specific position to delete it. I know that I should use a query of orderBy, but I need to get a specific child by its position.
Is there a way to do this? I only found a way to get the number of children with getChildrenCount() method of the snapshot, but didn't find something by passing the position value.
Thank you.
protected void populateViewHolder(final ReportViewHolder viewHolder, final Report report, int position) {
viewHolder.txtTitle.setText(report.title);
viewHolder.txtMessage.setText(report.message);
viewHolder.txtDate.setText(report.date);
viewHolder.txtuserName.setText(report.userName);
viewHolder.btnDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String key = report.key;
Query myTopPostsQuery = mDatabaseReference.child("user-reports/"+userID).orderByKey().equalTo(report.key);
myTopPostsQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
snapshot.getRef().removeValue();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mDatabaseReference.child("reports/"+ key).removeValue();
}
});
}
};
I want to use the position of populateViewHolder, to get the child position and then delete its node.
Now I added a field for report called key and using orderByKey().equalTo(report.key); to delete it.
I think you have to add delete and add methods to your adapter class.
public class AllAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<Article> articleList = new ArrayList<>();
Context context;
public AllAdapter(Context context){
this.context = context;
}
public void addItem(Article article){
articleList.add(article);
notifyDataSetChanged();
}
public void deleteItem(int position){
articleList.remove(position);
notiftyDateSetChanged(position);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_post_item,null);
return new ArticleViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return articleList.size();
}
class ArticleViewHolder extends RecyclerView.ViewHolder{
public ArticleViewHolder(View itemView) {
super(itemView);
}
}
}
Related
I have a lists in which each row will consist of multiple chips.
On each row I can able to type anything and suggestion would come and if I select any of the suggestion then chip will be added in same row just like auto complete text view.
I tried many things like adding views dynamically in linear layout and others but not getting the solution.
I appreciate If anyone knows how to do it.
This is my code run succesfully ;
package com.example.masterappinc;
public class Judgedetailadapter extends RecyclerView.Adapter {
Judgedetailreturn judgedetailreturn;
List<Judgedetailreturn> judgelist;
Context context;
public Judgedetailadapter(List<Judgedetailreturn> judgelist, Context context) {
this.judgelist = judgelist;
this.context = context;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater =LayoutInflater.from(context);
View view= inflater.inflate(R.layout.cardviewjudgedetail,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
final Judgedetailreturn judgedetailreturn1=judgelist.get(position);
holder.name.setText(judgedetailreturn1.getName());
String ide = judgedetailreturn1.getId();
holder.id.setText(ide);
holder.company.setText(judgedetailreturn1.getCompany());
holder.mobno.setText(judgedetailreturn1.getMobno());
holder.domain.setText(judgedetailreturn1.getDomain());
holder.email.setText(judgedetailreturn1.getEmail());
Firebase mref = new Firebase("https://master-app-inc.firebaseio.com/judgeid/"+ide+"/StudentIDalloted");
mref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Chip chip=new Chip(holder.chipGroup.getContext());
chip.setText(dataSnapshot.getValue().toString());
holder.chipGroup.addView(chip);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
#Override
public int getItemCount() {
return judgelist.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
ChipGroup chipGroup;
TextView name,id,email,mobno,company,domain;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.namejudegedetail);
id = itemView.findViewById(R.id.judgeidjudegedetail);
email = itemView.findViewById(R.id.emailidjudegedetail);
mobno = itemView.findViewById(R.id.mobilenojudgedetail);
company = itemView.findViewById(R.id.companynamejudegedetail);
domain= itemView.findViewById(R.id.domainjudgedetail);
chipGroup = itemView.findViewById(R.id.chipgrp);
}
}
public void toast(String x){
Toast.makeText(context,x,Toast.LENGTH_SHORT).show();
}
}
Hope this run !
I want remove selected item from recyclerView list.
In my list I have delete image icon each row and I want delete item when clicked delete image icon. How can do it?
My adapter code this is see my code how can do it:
thank you
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ItemViewHolder>{
private Context context;
private List<Items> items=new ArrayList<>();
public ListAdapter(Context context){
this.context=context;
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater=LayoutInflater.from(context);
View view=layoutInflater.inflate(R.layout.item,parent,false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
holder.bindItem(items.get(position));
}
#Override
public int getItemCount() {
return items.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder{
private TextView titleTextView;
private ImageView editIcon;
private ImageView deleteIcon;
public ItemViewHolder(View itemView) {
super(itemView);
titleTextView =itemView.findViewById(R.id.item_title);
editIcon=itemView.findViewById(R.id.item_edit);
deleteIcon=itemView.findViewById(R.id.item_delete);
}
public void bindItem(Items item){
titleTextView.setText(item.getTitle());
}
public void removeItem(int position){
items.remove(position);
notifyItemRemoved(position);
}
}
public void addItem(Items item){
items.add(item);
notifyItemInserted(items.size()-1);
}
}
Try below code
public ItemViewHolder(View itemView) {
super(itemView);
titleTextView =itemView.findViewById(R.id.item_title);
editIcon=itemView.findViewById(R.id.item_edit);
deleteIcon=itemView.findViewById(R.id.item_delete);
// put this code
deleteIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
removeItem(getAdapterPosition())
}
});
}
The answer above does the job but it is always better to use interface callback for easier implementation and code modularity. Below is the code that i like to write for removing the list item from activity. In this method you dont have to alter much code of adapter class and in case you want to do more complicated such as: remove the list element only when element from firebase database is removed, this method does this job perfectly.
here is a code snippet
new DeclinedClickListener() {
#Override
public void declinedClick(int position, View v) {
fbDB.getReference("news_requests").child(articles.get(position).getNewsID()).removeValue(new DatabaseReference.CompletionListener() {
#Override
public void onComplete(#Nullable DatabaseError databaseError, #NonNull DatabaseReference databaseReference) {
articles.remove(position);
if(article_req_rv.getAdapter()!=null) {
article_req_rv.getAdapter().notifyDataSetChanged();
}
}
});
you make a interface for it
public interface DeclinedClickListener {
void declinedClick(int position, View v);
}
Use this inteface in recyclerview
holder.declined_btx.setOnClickListener(l->{
declinedClickListener.declinedClick(position,l);
});
Sorry for my english. I have list objects, it list contains switch btn. When user change some switch i neeed it update in db. I
But when i try change swith, i have error:
java.lang.IllegalStateException: Cannot modify managed objects outside of a write transaction.
I can not understand how create adapter, who can update realtime data
My adapter:
public class DocumentTypeAdapterDB extends RealmRecyclerViewAdapter<DocType, DocumentTypeAdapterDB.ViewHolder> {
RealmList<DocType> docTypes;
public DocumentTypeAdapterDB(#Nullable RealmList<DocType> docTypes, Context context) {
super(docTypes, true);
this.docTypes = docTypes;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_doc_type, null);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutView.setLayoutParams(lp);
ViewHolder rcv = new ViewHolder(layoutView);
return rcv;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final DocType docType = docTypes.get(position);
holder.switch_item.setText(docType.name);
//check box
holder.switch_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!holder.switch_item.isChecked()) {
docType.is_check = false;
} else {
docType.is_check = true;
}
}
});
}
#Override
public int getItemCount() {
return docTypes.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
SwitchCompat switch_item;
public ViewHolder(View itemView) {
super(itemView);
switch_item = (SwitchCompat) itemView.findViewById(R.id.switch_item);
}
public void clearAnimation()
{ itemView.clearAnimation(); }
}
}
DocType
public class DocType extends RealmObject{
public boolean is_check;
public String name;
//getter and setter
}
You need transaction to modify RealmObjects.
So, you should get Realm instance that docTypes belongs to and then:
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
docType.is_check = holder.switch_item.isChecked();
}
});
I am trying to retrieve data from firebase database, when i try to retrieve data for the very first time after installing the app nothing is displayed in recycler view but when i press back and once again try to retrieve data,its displayed properly, suggest me changed which i should do in my code so that data is properly displayed in first attempt
Method Used to return ArrayList
public ArrayList<SaveAddInformation> retrieve(){
AdvertisementRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
SaveAddInformation mModel = eventSnapshot.getValue(SaveAddInformation.class);
Log.d("DATA" ,""+ mModel);
adinfolist.add(mModel);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return adinfolist;
}
Adpater Class
Context c;
ArrayList<SaveAddInformation> adinfolist;
public MyAdapter(Context c, ArrayList<SaveAddInformation> adinfolist) {
this.c = c;
this.adinfolist = adinfolist;
}
#Override
public MyViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(c).inflate(R.layout.design_row,parent,false);
MyViewholder myViewholder=new MyViewholder(v);
return myViewholder;
}
#Override
public void onBindViewHolder(MyViewholder holder, int position) {
SaveAddInformation save=adinfolist.get(position);
holder.titleTv.setText(save.getTitleS());
holder.rentamt.setText(save.getRent_amount());
holder.rentdays.setText(save.getRentDayS());
holder.desc.setText(save.getDescriptionS());
holder.setImage(getApplicationContext(), save.getImageuri());
// holder.titleTv.setText((CharSequence) adinfolist.get(position));
}
#Override
public int getItemCount() {
return adinfolist.size();
}
}
ViewHolder Class
public MyViewholder(View itemView) {
super(itemView);
titleTv=(TextView)itemView.findViewById(R.id.Titletextv);
rentamt=(TextView)itemView.findViewById(R.id.rent_amount);
rentdays=(TextView)itemView.findViewById(R.id.days_rent);
desc=(TextView)itemView.findViewById(R.id.descTV);
}
public void setImage(Context applicationContext, String imageuri) {
adimg=(ImageView)itemView.findViewById(R.id.ad_image);
// We Need TO pass Context
Picasso.with(applicationContext).load(imageuri).into(adimg);
}
If you are sure that the code has no errors, I would like to remind you that Firebase connections are async.
So the first time the function retrieve() returns the value of arrayList is actually empty.
What you can do is call adapter.notifyDataSetChanged() after the for loop in onDataChange() method.
I have two arraylist and I want to display the data in both list in the same recyclerview. My code looks like this.
My adapter
class NotificationAdapter extends RecyclerView.Adapter<NotificationViewHolder> {
//..
List<Notification> notifList = new ArrayList<>();
List<AcceptedInvitation> acceptedInvitations = new ArrayList<>();
Context context;
LayoutInflater inflater;
public NotificationAdapter(Context context){
this.context = context;
inflater = LayoutInflater.from(context);
}
public void addNotification(Notification notification){
notifList.add(notification);
notifyDataSetChanged();
notifyItemInserted(notifList.size());
}
public void addAcceptedInvitation(AcceptedInvitation invitation){
acceptedInvitations.add(invitation);
notifyDataSetChanged();
notifyItemInserted(acceptedInvitations.size());
}
#Override
public NotificationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.rv_notifications, parent, false);
NotificationViewHolder holder = new NotificationViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(final NotificationViewHolder holder, int position) {
String user1= null;
String user2= null;
if(position < notifList.size()){
user1= notifList.get(position).getUserName();
}else {
user2= acceptedInvitations.get(position).getUserName();
}
#Override
public int getItemCount() {
return notifList.size() + acceptedInvitations.size();
}
}
RecyclerView ViewHolder
public class NotificationViewHolder extends RecyclerView.ViewHolder {
//..
TextView userName;
public NotificationViewHolder(View itemView) {
super(itemView);
userName = (TextView) itemView.findViewById(R.id.display_name);
}
}
I have an error in onBindViewHolder() part. I'm using Firebase in retrieving the data by the way.
Main Activity(loadData() is called when the activity starts)
public void loadData(){
//..
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference().child("users").child(key).child("invitations");
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Notification notification = dataSnapshot.getValue(Notification.class);
adapter.addNotification(notification);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
DatabaseReference invitationRef = database.getReference().child("users").child(key).child("acceptedInvitations");
invitationRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
AcceptedInvitation acceptedInvitation = dataSnapshot.getValue(AcceptedInvitation.class);
Toast.makeText(getActivity(), dataSnapshot.getValue().toString(), Toast.LENGTH_LONG).show();
adapter.addAcceptedInvitation(acceptedInvitation);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I can already retrieve the data from invitations and acceptedInvitations json-array, but i have an error when I tried to populate the data from the acceptedInvitations, basically when I call "addAcceptedInvitation(acceptedInvitation)".
Error.
threadid=1: thread exiting with uncaught exception (group=0x41a81c80)
I assume you want to combine the Notification data and AcceptedInvitation data. Please note that when you call two Firebase Database call, the second one will be executed after the first one is finished. So it is okay to use this code below (because if not, this code is risky).
First, remove notifyItemInserted() inside addNotification and addAcceptedInvitation as it is no use if it's called directly after notifyDataSetChanged(). But if you prefer keeping notifyItemInserted() and removing notifyDataSetChanged(), it will be more complicated.
Then lets point out what went wrong. When you call notifyDataSetChanged(), your adapter will refresh all of its item. In your getItemCount(), you mention that your adapter have (notifList.size() + acceptedInvitations.size()). So if you have 3 notifList and 2 acceptedInvitations, your adapter will refresh from its first value to (3+2) fifth value.
Knowing that, the onBindViewHolder will be called with position value from 0 to 4 (0 is first, 4 is fifth). Look at the code:
#Override
public void onBindViewHolder(final NotificationViewHolder holder, int position) {
...
if(position < notifList.size()){
user1 = notifList.get(position).getUserName();
} else {
user2 = acceptedInvitations.get(position).getUserName();
}
}
Notice that when position is 0 or 1 or 2, it is fine because its executing notifList.get(position) and notifList on those index is exist. But when position is 3, its executing acceptedInvitations.get(position) that will triger error because acceptedInvitations only have value on index 0 and 1 not in 3
After understanding that, your code should look like this:
#Override
public void onBindViewHolder(final NotificationViewHolder holder, int position) {
...
if(position < notifList.size()){
user1 = notifList.get(position).getUserName();
} else {
user2 = acceptedInvitations.get(position - notifList.size()).getUserName();
}
}
Hope this help :)