Firebase Recycler View duplicate data - java

I'm trying to retrieve comments from the database but it shows all the comments as duplicate
This same listner works fine with fragments but gives duplicate item bug when implemented on Activity
private void startListening() {
Query query = mCommentsDatabase;
FirebaseRecyclerOptions<Comment> options =
new FirebaseRecyclerOptions.Builder<Comment>()
.setQuery(query, Comment.class)
.build();
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<Comment, CommentsViewHolder>(options){
#Override
public CommentsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create a new instance of the ViewHolder, in this case we are using a custom
// layout called R.layout.message for each item
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_comment_item, parent, false);
return new CommentsViewHolder(view);
}
#Override
protected void onBindViewHolder(final CommentsViewHolder holder, int position, final Comment model) {
mCommentsDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (dataSnapshot.exists() && dataSnapshot != null){
if (dataSnapshot.exists()){
String CommenterId = dataSnapshot.child("uid").getValue().toString();
mUsersDatabase.child(CommenterId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot userDataSnapshot) {
if (userDataSnapshot.exists()){
String username = userDataSnapshot.child("username").getValue().toString();
String thumbImage = userDataSnapshot.child("profile_thumbnail").getValue().toString();
String comment = dataSnapshot.child("body").getValue().toString();
Long timestamp = Long.parseLong(dataSnapshot.child("timestamp").getValue().toString());
GetTimeAgo getTimeAgo = new GetTimeAgo();
String time = getTimeAgo.getTimeAgo(timestamp, getApplicationContext());
holder.setName(username);
holder.setComment(comment);
holder.setImage(thumbImage, getApplicationContext());
holder.setTime(time);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
};
mCommentsList.setAdapter(adapter);
adapter.startListening();
}
Can someone help point to what's wrong?
I've implemented the same thing in fragments it's working but when used in an Activity it works weirdly.

Related

Use HashSet to weed out duplicate values. List returns either empty or returns duplicate values

I am trying to remove duplicate values from an ArrayList using HashSet, so that city names aren't returned more than once if they are the sameā€¦ The List comes back either empty or still shows duplicate values. Was hoping someone could tell me where the error is in my code, so that no duplicate values are returned...
I am using this for reference:
Set<String> set = new HashSet<>(yourList); yourList.clear(); yourList.addAll(set); , but can't figure out how to make it work in my code. Know it's probably a simple fix, but I've been playing around with it and still hasn't come back right...
Anyone can tell me where I am going wrong here? According to everyone so far the code looks like it should be working... Although it's not...
SearchCityFragment
public class SearchCityFragment extends Fragment {
private List<Post> mPostList;
private Set<Post> mPostSet;
private RecyclerView mRecyclerView;
private CityAdapter mCityAdapter;
private EditText mSearchBar;
private RelativeLayout mRelativeLayout;
private Activity mActivity;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search_city, container, false);
mRelativeLayout = view.findViewById(R.id.relative_layout_11);
mRelativeLayout.setVisibility(View.VISIBLE);
mRecyclerView = view.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(linearLayoutManager);
mPostList = new ArrayList<>();
mCityAdapter = new CityAdapter(getContext(), mPostList);
mRecyclerView.setAdapter(mCityAdapter);
mSearchBar = mActivity.findViewById(R.id.search_bar);
mSearchBar.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
searchCity(s.toString().toLowerCase());
}
#Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
private void searchCity(String s) {
Query query = FirebaseDatabase.getInstance().getReference("Posts").orderByChild("city").startAt(s).endAt(s + "\uf8ff");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPostList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
if (s.length() == 0) {
mPostList.clear();
mRelativeLayout.setVisibility(View.VISIBLE);
} else {
mRelativeLayout.setVisibility(View.GONE);
mPostList.add(post);
mPostSet = new HashSet<>(mPostList);
mPostList.clear();
mPostList.addAll(mPostSet);
readCity();
}
}
mCityAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void readCity() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (mSearchBar.getText().toString().equals("")) {
mPostList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
mPostList.add(post);
mPostSet = new HashSet<>(mPostList);
mPostList.clear();
mPostList.addAll(mPostSet);
}
mCityAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
if (context instanceof Activity) {
mActivity = (Activity) context;
}
}
}
if you only want to show the post with searched city and you want to show only one such post you can just query the database for post with that city , you don't need to create any arraylist or hashmap.
private void searchCity(String s) {
FirebaseDatabase.getInstance()
.getReference("Posts")
.orderByChild("city")
.startAt(s)
.limitToFirst(1).
.addValueEventListener(new ValueEvnetListener){
#Override
public void onDataChange(DataSnapshot
dataSnapshot) {
// do your rhing
}
#Override
public void onCancelled(DatabaseError databaseError) {}
} ;
}

Make String retrieved from database case insensitive even if it's saved to database as a capital letter, can be retrieved as lowercase

When a user saves a String to the database it usually begins with a capital letter, and that is the way that I would like it to remain. But then in my SearchFragment, the user types in the name of a certain place, or activity or whatever, and for example the word could be Nature Hike, or something, and I want at THIS moment (the search) for the title of the event saved in the database to not matter if it is a capital letter or lowercase.
How can I achieve this? If the String is already saved to the database, and another user searches for the that String, but instead of Nature Hike they write nature... then I want it to still come up.
Can someone tell me how to do this?
SearchEventsFragment
public class SearchEventsFragment extends Fragment {
RecyclerView mRecyclerView;
SearchEventsAdapter mSearchEventsAdapter;
List<Post> mPostList;
private EditText mSearchBar;
Activity mActivity;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search_events, container, false);
mRecyclerView = view.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mPostList = new ArrayList<>();
mSearchEventsAdapter = new SearchEventsAdapter(getContext(), mPostList);
mRecyclerView.setAdapter(mSearchEventsAdapter);
mSearchBar = mActivity.findViewById(R.id.search_bar);
mSearchBar.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
searchEvents(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
readEvents();
return view;
}
private void searchEvents(String s) {
Query query = FirebaseDatabase.getInstance().getReference("Posts").orderByChild("text_event").startAt(s).endAt(s + "\uf8ff");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mPostList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
mPostList.add(post);
}
mSearchEventsAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void readEvents() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (mSearchBar.getText().toString().equals("")) {
mPostList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
if (post != null) {
mPostList.add(post);
}
}
mSearchEventsAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
if (context instanceof Activity) {
mActivity = (Activity) context;
}
}
}

i am trying to make a chat activity in which users can chat personally.but some how only a singe data is been retrieve from the database

I am trying to learn to create a chat Activity and trying to retrieve all the message from the firebase when I send the message then the message is been stored in the firebase but at the time to receiving on the single message is been received.i am unable to understand the problem my code
personalChat.java//onstart method
protected void onStart() {
super.onStart();
rootRef.child("Message").child(CurrentUserId).child(msgReciverId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
message cMessage = dataSnapshot.getValue(message.class);
messageList.add(cMessage);
messageAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
message_adapter.java
public class message_adapter extends RecyclerView.Adapter<message_adapter.MessageViewHolder> {
private List<message> usermsgList;
private FirebaseAuth mAuth;
private DatabaseReference userref;
public message_adapter(List<message> usermsgList){
this.usermsgList = usermsgList;
}
#NonNull
#Override
public MessageViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.coustommsglayout,parent,false);
mAuth = FirebaseAuth.getInstance();
return new MessageViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final MessageViewHolder holder, int position) {
String msgsenderid = mAuth.getCurrentUser().getUid();
message Message = usermsgList.get(position);
String fromuserid = Message.getFfrom();
String fromMessageType = Message.getType();
userref = FirebaseDatabase.getInstance().getReference().child("User").child(fromuserid);
userref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("image")){
String reciverimage = dataSnapshot.child("image").getValue().toString();
//Picasso.get().load(reciverimage).into(holder.reciverProfileImage);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
if (fromMessageType.equals("Text")){
holder.recivermsgtext.setVisibility(View.INVISIBLE);
holder.reciverProfileImage.setVisibility(View.INVISIBLE);
if (fromuserid.equals(msgsenderid)){
holder.sendermsgtext.setBackgroundResource(R.drawable.sendermsglayout);
holder.sendermsgtext.setText(Message.getMessage());
}else{
holder.sendermsgtext.setVisibility(View.INVISIBLE);
holder.recivermsgtext.setVisibility(View.VISIBLE);
holder.reciverProfileImage.setVisibility(View.VISIBLE);
holder.recivermsgtext.setBackgroundResource(R.drawable.recivermsglayout);
holder.recivermsgtext.setText(Message.getMessage());
}
}
}
#Override
public int getItemCount() {
return usermsgList.size();
}
public class MessageViewHolder extends RecyclerView.ViewHolder{
public TextView sendermsgtext,recivermsgtext;
public CircleImageView reciverProfileImage;
public MessageViewHolder(#NonNull View itemView){
super(itemView);
sendermsgtext = (TextView) itemView.findViewById(R.id.sender);
recivermsgtext = (TextView) itemView.findViewById(R.id.reciver);
reciverProfileImage = (CircleImageView) itemView.findViewById(R.id.profile_msg_dp);
}
}
}
it should show all the msg available in the Message.child(currentuser).child(reciveruserid). but it only shows the first value. Please help me out with this problem
firebase Message node
Message
JsmvpdGLjLbg9mQ0TfmKForis5q2
PnYKrGiS7YUp9JdHNDMurOSbGBw1
-LoHAND5o_T8S2NRECAH
ffrom: "JsmvpdGLjLbg9mQ0TfmKForis5q2"
message: "hello"
type: "Text"
-LoJCo9T7IrkHxD5xlZR
ffrom: "JsmvpdGLjLbg9mQ0TfmKForis5q2"
message: "whtsup"
type: "Text"
-LoJE04JSfl3BPyU3r9T
ffrom: "JsmvpdGLjLbg9mQ0TfmKForis5q2"
message: "wtsup"
type: "Text"

java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1 from OnChildRemoved Firebase Database

I'm trying to remove data from my recyclerview and let it be updated in the mobile ui as well. It is an android app. I am able to delete the data alright but I always have to leave that page and come back when I make the changes. I tried making some modifications to the onChildRemoved method but I started getting crashes upon making this change. What do I do? Below is my code.
MainActivity.java
DatabaseReference databaseReference;
List<DataSnapshot> listData;
RecyclerView recyclerView;
MyCart.MyAdapter adapter;
recyclerView = findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
listData = new ArrayList<>();
adapter = new MyCart.MyAdapter(listData);
adapter.setHasStableIds(true);
GetDataFirebase();
private void GetDataFirebase() {
databaseReference = FirebaseDatabase.getInstance().getReference()
.child("Customers")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("My Cart");
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Items students = dataSnapshot.getValue(Items.class);
listData.add(dataSnapshot);
recyclerView.setAdapter(adapter);
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
int index = listData.indexOf(dataSnapshot);
listData.remove(index);
adapter.notifyDataSetChanged();
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Adapter Class
public class MyAdapter extends RecyclerView.Adapter<MyCart.MyAdapter.ViewHolder> {
List<DataSnapshot> list;
public MyAdapter(List<DataSnapshot> List) {
this.list = List;
}
#Override
public void onBindViewHolder(MyCart.MyAdapter.ViewHolder holder, int position) {
final DataSnapshot studentSnapshot = list.get(position);
final Items students = studentSnapshot.getValue(Items.class);
final String list_user_id = studentSnapshot.getKey();
holder.item_name.setText(students.getItem_name());
holder.item_price.setText(students.getItem_price());
Picasso.with(holder.item_image.getContext()).load(students.getItem_image()).placeholder(R.drawable.no_image_two).into(holder.item_image);
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DatabaseReference prod_ref = FirebaseDatabase.getInstance().getReference().child("Customers").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("My Cart").child(list_user_id);
prod_ref.removeValue();
adapter.notifyDataSetChanged();
Toast.makeText(MyCart.this, "Item removed from cart", Toast.LENGTH_SHORT).show();
}
});
}
#NonNull
#Override
public MyCart.MyAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cart_item_layout, parent, false);
return new MyCart.MyAdapter.ViewHolder(view);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView item_name, item_price;
ImageView item_image;
ImageView delete;
public ViewHolder(View itemView) {
super(itemView);
item_name = itemView.findViewById(R.id.item_name);
item_price = itemView.findViewById(R.id.item_price);
item_image = itemView.findViewById(R.id.item_image);
delete = itemView.findViewById(R.id.delete_item);
}
}
#Override
public int getItemCount() {
return list.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
}
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DatabaseReference prod_ref = FirebaseDatabase.getInstance().getReference().child("Customers").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("My Cart").child(list_user_id);
prod_ref.removeValue();
//add/modify these two lines here
list.remove(position);
notifyDataSetChanged();
}
});
And one more change you need to do
// move this toast to onChildRemoved method and clear the other code from there
Toast.makeText(MyCart.this, "Item removed from cart", Toast.LENGTH_SHORT).show();
like
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
//remove these line these will raise the exception and Toast here
int index = listData.indexOf(dataSnapshot);
listData.remove(index);
adapter.notifyDataSetChanged();
}
When dataSnapshot does not exist in list, it returns -1. Index of list start from 0. Therefore, you're this getting error. You need to add a guard check here like:
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
int index = listData.indexOf(dataSnapshot);
if(index > 0) {
listData.remove(index);
}
adapter.notifyDataSetChanged();
}

Simultaneous Arraylists

Firebase
FirebaseRecyclerOptions<SQLiteHelper> options =
new FirebaseRecyclerOptions.Builder<SQLiteHelper>()
.setQuery(mFetchingMessages, SQLiteHelper.class)
.build();
final MainData mHelper = new MainData(this);
final Cursor csr = myDBHlpr.getAllQuestions3();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<SQLiteHelper, Chat.MessagesViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull final Chat.MessagesViewHolder holder, final int position, #NonNull final SQLiteHelper model) {
final DatabaseReference mTimeReference = FirebaseDatabase.getInstance().getReference().child("Messages").child(MessageSenderId).child(MessageRecieverId);
Query messageQuery = mTimeReference.limitToLast(10);
messageQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
SQLiteHelper message = dataSnapshot.getValue(SQLiteHelper.class);
}
#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) {
}
});
messages.add(message);
}
}
#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 Chat.MessagesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.custom_activity_chat, parent, false);
return new Chat.MessagesViewHolder(view);
}
};
messageList.setAdapter(firebaseRecyclerAdapter);
firebaseRecyclerAdapter.startListening();
SQLite
while (csr.moveToNext()) {
String mSender = csr.getString(csr.getColumnIndex(KEY_SENDER));
String mMessage = csr.getString(csr.getColumnIndex(KEY_MESSAGE));
long mTime = csr.getLong(csr.getColumnIndex(KEY_TIME));
String mSeen = csr.getString(csr.getColumnIndex(KEY_SEEN));
String mTimer = csr.getString(csr.getColumnIndex(KEY_TIMER));
String mType = csr.getString(csr.getColumnIndex(KEY_TYPE));
messages.add(new SQLiteHelper(mSender, mMessage, mType, mSeen, mTimer, mTime));
mAdapter.notifyDataSetChanged();
When i have both only the firebase data is shown and when i remove or comment the firebase part of code the sqlite part of code is shown in recyclerview. Can someone suggest me to make the firebase code show below the sqlite code somehow please?

Categories

Resources