I have a firebase strucuture as
The recycler view is only displaying the last added or say latest added node to the database instead of displaying each and every node
the database reference i am using is
r2 = FirebaseDatabase.getInstance().getReference().child("Uploads").child("Wheat").child(S).child(D).child(T).child(FirebaseAuth.getInstance().getUid());
and the code for recycler view is as
public class MyPost extends AppCompatActivity {
private RecyclerView recyclerView;
private DatabaseReference r, r2, r3;
private String S, D, T;
FirebaseRecyclerAdapter<RecyclerCropView, ViewHolder2> Fbra1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_post);
r = FirebaseDatabase.getInstance().getReference().child("User_Data").child(MainDashboard.type).child(FirebaseAuth.getInstance().getUid());
recyclerView = (RecyclerView) findViewById(R.id.R_view2);
r.addListenerForSingleValueEvent(rr);
}
private ValueEventListener rr = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
S = dataSnapshot.child("State").getValue().toString();
D = dataSnapshot.child("City").getValue().toString();
T = dataSnapshot.child("Tehsil").getValue().toString();
// Toast.makeText(MyPost.this,S+D+T.toString(),Toast.LENGTH_LONG).show();
r2 = FirebaseDatabase.getInstance().getReference().child("Uploads").child("Wheat").child(S).child(D).child(T).child(FirebaseAuth.getInstance().getUid());
// Toast.makeText(MyPost.this,r2.toString(),Toast.LENGTH_LONG).show();
r2.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
r3=r2.child(dataSnapshot.getKey());
Toast.makeText(MyPost.this, r3.toString(), Toast.LENGTH_LONG).show();
FirebaseRecyclerOptions<RecyclerCropView> options = new FirebaseRecyclerOptions.Builder<RecyclerCropView>().setQuery(r3, RecyclerCropView.class).build();
Fbra1 = new FirebaseRecyclerAdapter<RecyclerCropView, ViewHolder2>(options) {
#Override
protected void onBindViewHolder(#NonNull ViewHolder2 holder, int position, #NonNull RecyclerCropView model) {
holder.setProductImage(model.getProduct_Image());
holder.setProduct(model.getProduct());
holder.setMax(model.getMaximumPrice());
holder.setQuantityUnit(model.getQuantityUnit());
holder.setQuantity(model.getQuantity());
}
#NonNull
#Override
public ViewHolder2 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_post, parent, false);
return new ViewHolder2(v);
}
};
Fbra1.notifyDataSetChanged();
recyclerView.hasFixedSize();
recyclerView.setLayoutManager(new LinearLayoutManager(MyPost.this));
Fbra1.startListening();
recyclerView.setAdapter(Fbra1);
}
#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) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
#Override
protected void onRestart() {
super.onRestart();
finish();
}
}
Recycler view is only showing very last item that was added to database.
Note:-
The item.xml file has width set to wrap content.
if i remove the childEventListener the recyclerView shows multiple items with
null on the place of TextView(These are those textView on which data retrived was supposed to be set)
Here is the problem: r2.addChildEventListener
Classes implementing this interface can be used to receive events about changes in the child locations of a given DatabaseReference ref. Attach the listener to a location using addChildEventListener(ChildEventListener) and the appropriate method will be triggered when changes occur.
Firebase Docs
What you should use is a r2.addListenerForSingleValueEvent
This returns the children of the specific node. But now since you are using FirebaseUI library, you will not need to listen as it is a listener itself.
So your code should listen to the root of the posts. This r3=r2.child(dataSnapshot.getKey()); is unnecessary because it only gets one entry
Change to this
FirebaseRecyclerOptions<RecyclerCropView> options = new FirebaseRecyclerOptions.Builder<RecyclerCropView>().setQuery(r2, RecyclerCropView.class).build();
Fbra1 = new FirebaseRecyclerAdapter<RecyclerCropView, ViewHolder2>(options) {
#Override
protected void onBindViewHolder(#NonNull ViewHolder2 holder, int position, #NonNull RecyclerCropView model) {
holder.setProductImage(model.getProduct_Image());
holder.setProduct(model.getProduct());
holder.setMax(model.getMaximumPrice());
holder.setQuantityUnit(model.getQuantityUnit());
holder.setQuantity(model.getQuantity());
}
#NonNull
#Override
public ViewHolder2 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_post, parent, false);
return new ViewHolder2(v);
}
};
Fbra1.notifyDataSetChanged();
recyclerView.hasFixedSize();
recyclerView.setLayoutManager(new LinearLayoutManager(MyPost.this));
Fbra1.startListening();
recyclerView.setAdapter(Fbra1);
Related
I try to implement a friend request feature in the fragment using custom adapter with firebase database. The problem is when a user accepts or delete someone request, it deletes from firebase but not properly update in the RecyclerView. this problems occurred in only runtime. If I refresh the page then my problem goes away.
Let I have two friend request. If I delete 2nd data then 2nd data will gone from RecyclerView but the problem is RecyclerView shows 1st data doubles. and if I delete 1st data then 1st data goes in the 2nd row and 2nd data came into the first row.
here is my database screenshot
Fragment class-
public class NotificationFragment extends Fragment {
private RecyclerView NotificationRecyclerView;
private NotificationAdapter adapter;
private List<Friend> friendList;
public NotificationFragment() {
// 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_notification, container, false);
NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
NotificationRecyclerView.setHasFixedSize(true);
LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
NotificationRecyclerView.setLayoutManager(LayoutManager);
friendList = new ArrayList<>();
adapter = new NotificationAdapter(getContext(), friendList);
NotificationRecyclerView.setAdapter(adapter);
readAllNotification();
return view;
}
private void readAllNotification() {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Friend friend = snapshot.getValue(Friend.class);
if (firebaseUser.getUid().equals(friend.getReceiverID())) {
friendList.add(friend);
}
}
Collections.reverse(friendList);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Custom Adapter -
public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder> {
private Context context;
private List<Friend> friendList;
public NotificationAdapter(Context context, List<Friend> friendList) {
this.context = context;
this.friendList = friendList;
}
#NonNull
#Override
public NotificationViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.single_notification_item, parent, false);
return new NotificationAdapter.NotificationViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position) {
final Friend friend = friendList.get(position);
getUserInfo(holder.profileImage, holder.NotificationUserName, friend.getSenderID());
holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase.getInstance().getReference("FriendRequest")
.child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
removeItem(position);
Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
}
});
}
});
}
public void removeItem(int position) {
friendList.remove(position);
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return friendList.size();
}
private void getUserInfo(final CircleImageView prfileImage, final TextView NotificationUserName, String senderID) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(senderID);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Users users = dataSnapshot.getValue(Users.class);
NotificationUserName.setText(users.getUserName());
Picasso.with(context).load(users.getImageUrl()).into(prfileImage);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public class NotificationViewHolder extends RecyclerView.ViewHolder {
private TextView NotificationUserName;
private Button cancelRequestButton;
private CircleImageView profileImage;
public NotificationViewHolder(#NonNull View itemView) {
super(itemView);
NotificationUserName = itemView.findViewById(R.id.NotificationUserName);
cancelRequestButton = itemView.findViewById(R.id.cancelRequestBtn);
profileImage = itemView.findViewById(R.id.profileImage);
}
}
}
My APP Problems screenshot -
let I have two request
1) if I delete 2nd data 1st data show doubles:
2) if I delete 1st data, 1st data goes into 2nd row and 2nd data came into 1st row:
Replace
removeItem(position);
with
removeItem(holder.getAdapterPosition());
You initialize your recyclerView and adapter in onCreateView which was not appropriate.You have to override the method onViewCreated then initialize your recyclerView and adapter.try like this
public class NotificationFragment extends Fragment {
private RecyclerView NotificationRecyclerView;
private NotificationAdapter adapter;
private List<Friend> friendList;
public NotificationFragment() {
// 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_notification, container, false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
NotificationRecyclerView.setHasFixedSize(true);
LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
NotificationRecyclerView.setLayoutManager(LayoutManager);
friendList = new ArrayList<>();
adapter = new NotificationAdapter(getContext(), friendList);
NotificationRecyclerView.setAdapter(adapter);
readAllNotification();
}
private void readAllNotification() {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Friend friend = snapshot.getValue(Friend.class);
if (firebaseUser.getUid().equals(friend.getReceiverID())) {
friendList.add(friend);
}
}
Collections.reverse(friendList);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Ok I just noticed you passed a parameter in removeItem method using holder.getAdapterPosition() which is causing your problem.Try to pass the position which is provided by public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position).So the basic error is when you are in onBindViewHolder you don't need to use holder.getAdapterPosition() because onBindViewHolder already giving you the position
In your removeItem method use notifyDataSetChanged instead of notifyItemRemoved(position)
try like this
#Override
public void onBindViewHolder(#NonNull final NotificationViewHolder holder, final int position) {
final Friend friend = friendList.get(position);
holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase.getInstance().getReference("FriendRequest").child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
removeItem(position);
Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
}
});
}
});
}
public void removeItem(int position) {
friendList.remove(position);
notifyDataSetChanged();
}
I've checked each and every bit of code in order to successfully render the data on recyclerview from Firebase, but still cannot figure out the problem.
Nothing is show on the logcat when I use Log.d for getting the children of the snapshot(means line is not executed). Can anybody point out the error.
public class MyOrders extends AppCompatActivity {
private static final String TAG = "MyOrders";
DatabaseReference databaseReference;
FirebaseRecyclerAdapter firebaseRecyclerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_orders);
RecyclerView myOrderList = findViewById(R.id.myOrderList);
Query query = FirebaseDatabase.getInstance().getReference("Requests").orderByChild("name").equalTo(User.currentUser.getUserName());
FirebaseRecyclerOptions<Request> options = new FirebaseRecyclerOptions.Builder<Request>().setQuery(query, new SnapshotParser<Request>() {
#NonNull
#Override
public Request parseSnapshot(#NonNull DataSnapshot snapshot) {
Log.d(TAG, "onCreate: "+snapshot.getChildrenCount());
return new Request(snapshot.child("name").getValue().toString(), snapshot.child("phone").getValue().toString(), snapshot.child("address").getValue().toString(), snapshot.child("total").getValue().toString());
}
}).build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Request, MyOrdersViewHolder>(options){
#NonNull
#Override
public MyOrdersViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.my_order_template, viewGroup, false);
return new MyOrdersViewHolder(v);
}
#Override
protected void onBindViewHolder(#NonNull MyOrdersViewHolder holder, int position, #NonNull Request model) {
Log.d(TAG, "onCreate: "+position);
holder.setOrder_id(firebaseRecyclerAdapter.getRef(position).getKey());
holder.setOrder_status(model.getOrderStatus());
holder.setOrder_items(model.getRequestedOrderList().size()+"");
holder.setItemClickLitener(new ItemClickLitener() {
#Override
public void onClick(View v, int pos, boolean isLongClick) {
Toast.makeText(MyOrders.this, ""+"Pending Action", Toast.LENGTH_SHORT).show();
}
});
}
};
myOrderList.setAdapter(firebaseRecyclerAdapter);
}
#Override
protected void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
firebaseRecyclerAdapter.stopListening();
}
}
The display from the Firebase database works fine, but when I try to delete an item from the database, the application crashes, although the deletion occurs. Writes on a null object reference in the string:
String postDescription = dataSnapshot.child("desc").getValue().toString();
Here is my code:
public class PostFragment extends Fragment {
private RecyclerView recyclerPost;
private DatabaseReference postReference;
private View view;
private LinearLayoutManager layoutManager;
public PostFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_post, container, false);
recyclerPost = view.findViewById(R.id.recycler_post);
postReference = FirebaseDatabase.getInstance().getReference().child("Posts");
postReference.keepSynced(true);
layoutManager = new LinearLayoutManager(getContext());
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
recyclerPost.setHasFixedSize(true);
recyclerPost.setLayoutManager(layoutManager);
return view;
}
#Override
public void onStart() {
super.onStart();
Query query = postReference.orderByChild("timestamp");
FirebaseRecyclerOptions<Posts> options =
new FirebaseRecyclerOptions.Builder<Posts>()
.setQuery(query, Posts.class)
.build();
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<Posts, PostViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull final PostViewHolder holder, int position, #NonNull final Posts model) {
final String postId = getRef(position).getKey();
postReference.child(postId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String postDescription = dataSnapshot.child("desc").getValue().toString();
holder.postDesc.setText(postDescription);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
holder.delBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
postReference.child(postId).removeValue();
}
});
}
#NonNull
#Override
public PostViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int position) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.blog_item, viewGroup, false);
return new PostViewHolder(view);
}
};
adapter.startListening();
recyclerPost.setAdapter(adapter);
}
public class PostViewHolder extends RecyclerView.ViewHolder {
private TextView postDesc;
private Button delBtn;
private View view;
public PostViewHolder(#NonNull View itemView) {
super(itemView);
view = itemView;
postDesc = (TextView) view.findViewById(R.id.post_description);
delBtn = (Button) view.findViewById(R.id.del_post_btn);
}
}
}
Please tell me the solution to this problem.
You can try the following:
postReference.child(postId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
String postDescription = dataSnapshot.child("desc").getValue().toString();
holder.postDesc.setText(postDescription);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
You can use the method exists():
public boolean exists ()
Returns true if the snapshot contains a non-null value.
It will check if the datasnapshot is in the
database, if it is not in the database then you can add a snackbar or a toast.
More information here:
https://firebase.google.com/docs/reference/android/com/google/firebase/database/DataSnapshot#exists()
Every time a post is added to the adapter/list view, you now create a listener with addValueEventListener in your onBindViewHolder. This listener gets the value from the database, and then keeps listening for changes until you remove it. Since you never remove these listeners, over time they add up and things likely get out of sync.
The simplest solution is to use addListenerForSingleValueEvent:
#Override
protected void onBindViewHolder(#NonNull final PostViewHolder holder, int position, #NonNull final Posts model) {
final String postId = getRef(position).getKey();
postReference.child(postId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String postDescription = dataSnapshot.child("desc").getValue().toString();
holder.postDesc.setText(postDescription);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
When you use addListenerForSingleValueEvent, the listener is removed right after onDataChange fires for the first time.
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 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 :)