Hey Guys i try to change the Query in Firebase depending on the selected user. But when i update the Query the Recyclerview stops showing data. Below is my Code. I would really appreciate if someone could take a look. I'm using the Recyclerview provided by Firebase. The database I'm using is Firestore.
package com.larinet.veikkokrypczyk.myfamilyandfriends;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.Query;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* A simple {#link Fragment} subclass.
*/
public class LocationListFragment extends Fragment {
ProgressBar progressBar;
RecyclerView locationList;
private static final String TAG = "LocationListFragment";
private FirebaseFirestore db;
private FirestoreRecyclerAdapter adapter;
LinearLayoutManager linearLayoutManager;
private FirebaseAuth mAuth;
private FirebaseUser currentUser;
private Query query;
private FirestoreRecyclerOptions<LocationEntity> response;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAuth = FirebaseAuth.getInstance();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_location_list, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
db = FirebaseFirestore.getInstance();
progressBar = view.findViewById(R.id.progress_bar);
locationList = view.findViewById(R.id.locationdata_rv);
linearLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
locationList.setLayoutManager(linearLayoutManager);
currentUser = mAuth.getCurrentUser();
UserEntity user = new UserEntity(currentUser.getDisplayName(), currentUser.getUid());
getInitialData(user);
}
public void getInitialData(UserEntity user){
//FAILED_PRECONDITION: The query requires an index. You can create it here:
query = db.collection("locations").orderBy("date", Query.Direction.DESCENDING).whereEqualTo("id", user.getId());
response = new FirestoreRecyclerOptions.Builder<LocationEntity>()
.setQuery(query, LocationEntity.class)
.build();
attachRecyclerViewAdapter();
adapter.notifyDataSetChanged();
}
public void getLocationDataForUser(UserEntity user){
//FAILED_PRECONDITION: The query requires an index. You can create it here:
query = db.collection("locations").orderBy("date", Query.Direction.DESCENDING).whereEqualTo("id", user.getId());
response = new FirestoreRecyclerOptions.Builder<LocationEntity>()
.setQuery(query, LocationEntity.class)
.build();
adapter.notifyDataSetChanged();
}
private void attachRecyclerViewAdapter() {
adapter = new FirestoreRecyclerAdapter<LocationEntity, FriendsHolder>(response) {
#Override
public void onBindViewHolder(FriendsHolder holder, int position, LocationEntity model) {
progressBar.setVisibility(View.GONE);
holder.locationLat.setText(Double.toString(model.getGeoPoint().getLatitude()));
holder.locationLong.setText(Double.toString(model.getGeoPoint().getLongitude()));
holder.userName.setText(model.getUserName());
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm", Locale.GERMAN);
String time = sdf.format(model.getDate());
holder.date.setText(time);
holder.itemView.setOnClickListener(v -> {
Snackbar.make(locationList, Double.toString(model.getGeoPoint().getLatitude())+", "+Double.toString(model.getGeoPoint().getLongitude()), Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
});
}
#Override
public FriendsHolder onCreateViewHolder(ViewGroup group, int i) {
View view = LayoutInflater.from(group.getContext())
.inflate(R.layout.recyclerview_row, group, false);
return new FriendsHolder(view);
}
#Override
public void onError(FirebaseFirestoreException e) {
Log.e("error", e.getMessage());
}
};
locationList.setAdapter(adapter);
}
public class FriendsHolder extends RecyclerView.ViewHolder {
TextView locationLat;
TextView locationLong;
TextView userName;
TextView date;
public FriendsHolder(View itemView) {
super(itemView);
locationLat = itemView.findViewById(R.id.locationLat);
locationLong = itemView.findViewById(R.id.locationLong);
userName = itemView.findViewById(R.id.userName);
date = itemView.findViewById(R.id.date);
}
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
so my Solution now looks like the following:
public void getInitialData(UserEntity user){
//FAILED_PRECONDITION: The query requires an index. You can create it here:
query = db.collection("locations").orderBy("date", Query.Direction.DESCENDING).whereEqualTo("id", user.getId());
response = new FirestoreRecyclerOptions.Builder<LocationEntity>()
.setQuery(query, LocationEntity.class)
.build();
attachRecyclerViewAdapter();
adapter.notifyDataSetChanged();
}
public void getLocationDataForUser(UserEntity user){
adapter.stopListening();
//FAILED_PRECONDITION: The query requires an index. You can create it here:
query = db.collection("locations").orderBy("date", Query.Direction.DESCENDING).whereEqualTo("id", user.getId());
response = new FirestoreRecyclerOptions.Builder<LocationEntity>()
.setQuery(query, LocationEntity.class)
.build();
attachRecyclerViewAdapter();
adapter.startListening();
adapter.notifyDataSetChanged();
}
The important part seems to be to stop listening and start listening by your own if you change the query also i need to reinstantiate the Adapter. I honestly don't know if all of this is good practice but it works..
Related
This question already has answers here:
Android - Client-side sorting with FirebaseRecyclerAdapter
(1 answer)
FirebaseRecyclerPagingAdapter - sort list by date
(1 answer)
Cannot retrieve data in ascending order
(2 answers)
Firebase Data Desc Sorting in Android
(19 answers)
How to arrange firebase database data in ascending or descending order?
(2 answers)
Closed 8 months ago.
As now i am working on a chat application, here i have a problem that how can i display my last recent chat on the top of the recyclerview in ChatlistFragment,
for example if i had recently sent my last message to any user they have to displayed at the top of my recyclerview, here is my code
package com.micoder.whatsappclone;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.github.clans.fab.FloatingActionButton;
import com.github.clans.fab.FloatingActionMenu;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.squareup.picasso.Picasso;
import de.hdodenhof.circleimageview.CircleImageView;
public class ChatsFragment extends Fragment {
private View PrivateChatsView;
private RecyclerView chatsList;
private DatabaseReference ChatsRef, UsersRef;
private FirebaseAuth mAuth;
private String currentUserID;
FloatingActionMenu fabMenu;
FloatingActionButton fabSettings, fabShare, fabContactDev;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
PrivateChatsView = inflater.inflate(R.layout.fragment_chats, container, false);
mAuth = FirebaseAuth.getInstance();
currentUserID = mAuth.getCurrentUser().getUid();
ChatsRef = FirebaseDatabase.getInstance().getReference().child("Messages").child(currentUserID);
UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
chatsList = (RecyclerView) PrivateChatsView.findViewById(R.id.chats_list);
chatsList.setLayoutManager(new LinearLayoutManager(getContext()));
fabOptions();
return PrivateChatsView;
}
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerOptions<Contacts> options =
new FirebaseRecyclerOptions.Builder<Contacts>()
.setQuery(ChatsRef, Contacts.class)
.build();
FirebaseRecyclerAdapter<Contacts, ChatsViewHolder> adapter =
new FirebaseRecyclerAdapter<Contacts, ChatsViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull ChatsViewHolder holder, int position, #NonNull Contacts model) {
final String usersIDs = getRef(position).getKey();
final String[] retImage = {"default_image"};
UsersRef.child(usersIDs).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child("userState").hasChild("state")) {
String state = dataSnapshot.child("userState").child("state").getValue().toString();
if (state.equals("online")) {
holder.onlineIcon.setVisibility(View.VISIBLE);
}
else if (state.equals("offline")) {
holder.onlineIcon.setVisibility(View.INVISIBLE);
}
}
else {
holder.onlineIcon.setVisibility(View.INVISIBLE);
}
if (dataSnapshot.exists()) {
if (dataSnapshot.hasChild("image")) {
retImage[0] = dataSnapshot.child("image").getValue().toString();
Picasso.get().load(retImage[0]).placeholder(R.drawable.profile_image).into(holder.profileImage);
}
final String retName = dataSnapshot.child("name").getValue().toString();
holder.userName.setText(retName);
if (dataSnapshot.child("userState").hasChild("state")) {
String state = dataSnapshot.child("userState").child("state").getValue().toString();
String date = dataSnapshot.child("userState").child("date").getValue().toString();
String time = dataSnapshot.child("userState").child("time").getValue().toString();
if (state.equals("online")) {
holder.userStatus.setText("online");
}
else if (state.equals("offline")) {
holder.userStatus.setText("Last Seen: " + date + " " + time);
}
}
else {
holder.userStatus.setText("offline");
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent chatIntent = new Intent(getContext(), ChatActivity.class);
chatIntent.putExtra("visit_user_id", usersIDs);
chatIntent.putExtra("visit_user_name", retName);
chatIntent.putExtra("visit_image", retImage[0]);
startActivity(chatIntent);
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#NonNull
#Override
public ChatsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.users_display_chats_layout, viewGroup, false);
return new ChatsViewHolder(view);
}
};
chatsList.setAdapter(adapter);
adapter.startListening();
}
public static class ChatsViewHolder extends RecyclerView.ViewHolder {
CircleImageView profileImage;
TextView userName, userStatus;
ImageView onlineIcon;
public ChatsViewHolder(#NonNull View itemView) {
super(itemView);
profileImage = itemView.findViewById(R.id.users_profile_image);
userName = itemView.findViewById(R.id.user_profile_name);
userStatus = itemView.findViewById(R.id.user_status);
onlineIcon = itemView.findViewById(R.id.user_online_status);
}
}
public void fabOptions() {
//FAB
fabMenu=PrivateChatsView.findViewById(R.id.fabMenu);
fabSettings=PrivateChatsView.findViewById(R.id.fabSettings);
fabContactDev=PrivateChatsView.findViewById(R.id.fabContactDev);
fabShare=PrivateChatsView.findViewById(R.id.fabShare);
fabShare.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "My application name");
String shareMessage= "\nLet me recommend you this application\n\n";
shareMessage = shareMessage + "https://play.google.com/store/apps/developer?id=MI_CODER"+"\n\n";
shareIntent.putExtra(Intent.EXTRA_TEXT, shareMessage);
startActivity(Intent.createChooser(shareIntent, "choose one"));
} catch(Exception e) {
//e.toString();
}
fabMenu.close(true);
}
});
fabSettings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "Settings", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getActivity(),SettingsActivity.class));
fabMenu.close(true);
}
});
fabContactDev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(),"Loading...",Toast.LENGTH_SHORT).show();
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://micoder-dev.github.io/Resume-Page/"));
startActivity(browserIntent);
fabMenu.close(true);
}
});
}
}
if you need to refer my complete source code you can get here => https://github.com/Micoder-dev/ChatApp-FE-UI.git
I think this will help you to make it easier to get a solution.
I have been trying to create a chat application and have implemented it using firestore database. The chat functionality works fine but as soon as the screen is filled and some scrolling is required to see the previous messages, the database updates in a weird way and the order becomes random and sometimes recent messages show up and sometimes older messages show up as a new message. I have used timestamp to order them but it doesn't seem to work. Even after using pagination, it didn't help. The data and order seem to change while scrolling the recycler view. I will put up the code and some screen shots for a better understanding.
Message Model.java
public class MessageModel {
String message, senderID, receiverID;
Long timestamp;
public MessageModel() {
}
public MessageModel(String senderID, String receiverID, String message, Long timestamp) {
this.senderID = senderID;
this.receiverID = receiverID;
this.message = message;
this.timestamp = timestamp;
}
public MessageModel(String senderID, String message) {
this.senderID = senderID;
this.message = message;
}
public String getReceiverID() {
return receiverID;
}
public void setReceiverID(String receiverID) {
this.receiverID = receiverID;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public String getSenderID() {
return senderID;
}
public void setSenderID(String senderID) {
this.senderID = senderID;
}
}
Message Adapter
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.chatdemo.Models.MessageModel;
import com.example.chatdemo.databinding.ReceiverTextItemBinding;
import com.example.chatdemo.databinding.SenderTextItemBinding;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class NewMessageAdapter extends RecyclerView.Adapter {
private ReceiverTextItemBinding receiverTextItemBinding;
private SenderTextItemBinding senderTextItemBinding;
private Context context;
private FirebaseUser fUser;
private int SENDER_VIEW_TYPE = 1, RECEIVER_VIEW_TYPE = 2;
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MMM-yy KK:mm a", Locale.US);
private List<MessageModel> mMessage;
public NewMessageAdapter(Context context, List<MessageModel> mMessage) {
this.context = context;
this.mMessage = mMessage;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == SENDER_VIEW_TYPE) {
senderTextItemBinding = SenderTextItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new SenderViewHolder(senderTextItemBinding.getRoot());
} else {
receiverTextItemBinding = ReceiverTextItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ReceiverViewHolder(receiverTextItemBinding.getRoot());
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
MessageModel messageModel = mMessage.get(position);
if (holder.getClass() == SenderViewHolder.class) {
senderTextItemBinding.tvSenderText.setText(messageModel.getMessage());
senderTextItemBinding.tvSenderTextTime.setText(simpleDateFormat
.format(new Date(Long.parseLong(messageModel.getTimestamp().toString()))));
} else {
receiverTextItemBinding.tvReceiverText.setText(messageModel.getMessage());
receiverTextItemBinding.tvReceiverTextTime.setText(simpleDateFormat
.format(new Date(Long.parseLong(messageModel.getTimestamp().toString()))));
}
}
#Override
public int getItemCount() {
return mMessage.size();
}
#Override
public int getItemViewType(int position) {
fUser = FirebaseAuth.getInstance().getCurrentUser();
if (mMessage.get(position).getSenderID().equals(fUser.getUid())) {
return SENDER_VIEW_TYPE;
} else {
return RECEIVER_VIEW_TYPE;
}
}
public class ReceiverViewHolder extends RecyclerView.ViewHolder {
private TextView receivedMessage, receivedTime;
public ReceiverViewHolder(#NonNull View itemView) {
super(itemView);
receivedMessage = receiverTextItemBinding.tvReceiverText;
receivedTime = receiverTextItemBinding.tvReceiverTextTime;
}
}
public class SenderViewHolder extends RecyclerView.ViewHolder {
private TextView sentMessage, sentTime;
public SenderViewHolder(#NonNull View itemView) {
super(itemView);
sentMessage = senderTextItemBinding.tvSenderText;
sentTime = senderTextItemBinding.tvSenderTextTime;
}
}
}
Chat Activity
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.example.chatdemo.Adapters.ChatAdapter;
import com.example.chatdemo.Adapters.NewMessageAdapter;
import com.example.chatdemo.Constants.Constants;
import com.example.chatdemo.Models.MessageModel;
import com.example.chatdemo.databinding.ActivityChatDetailBinding;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.ListenerRegistration;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class ChatDetailActivity extends AppCompatActivity {
private ActivityChatDetailBinding binding;
private Constants constants;
private MessageModel messageModel;
private FirebaseAuth firebaseAuth;
private FirebaseFirestore firestoreDB;
private String userID;
private FirestoreRecyclerOptions<MessageModel> options;
private ChatAdapter chatAdapter;
public static final String TAG = "paginate";
private NewMessageAdapter newMessageAdapter;
private RecyclerView recyclerView;
private List<MessageModel> mMessage;
private final int limit = 15;
private DocumentSnapshot lastVisible;
private boolean isScrolling = false;
private boolean isLastItemReached = false;
private String senderID, receiverID, receiverName, receiverPhoto;
private CollectionReference collectionReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityChatDetailBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
firebaseAuth = FirebaseAuth.getInstance();
firestoreDB = FirebaseFirestore.getInstance();
userID = firebaseAuth.getUid();
constants = new Constants();
senderID = firebaseAuth.getUid();
receiverID = getIntent().getStringExtra("receiverID");
receiverName = getIntent().getStringExtra("receiverName");
receiverPhoto = getIntent().getStringExtra("receiverPhoto");
binding.chatUserName.setText(receiverName);
Glide.with(getApplicationContext())
.load(Uri.parse(receiverPhoto))
.into(binding.chatUserImage);
binding.btnChatBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Go back
startActivity(new Intent(ChatDetailActivity.this, MainActivity.class));
}
});
collectionReference = firestoreDB.collection(constants.getChats())
.document(userID)
.collection(constants.getMessages())
.document(receiverID)
.collection(constants.getMessages());
binding.btnSendChat.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!binding.etMessage.getText().toString().equals("")) {
String message = binding.etMessage.getText().toString().trim();
messageModel = new MessageModel(senderID, receiverID, message, new Date().getTime());
binding.etMessage.setText("");
ProgressDialog progressDialog = new ProgressDialog(ChatDetailActivity.this);
progressDialog.setMessage("Sending...");
progressDialog.show();
firestoreDB.collection(constants.getChats())
.document(userID)
.collection(constants.getMessages())
.document(receiverID)
.collection(constants.getMessages())
.add(messageModel)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
firestoreDB.collection(constants.getChats())
.document(receiverID)
.collection(constants.getMessages())
.document(userID)
.collection(constants.getMessages())
.add(messageModel)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
progressDialog.dismiss();
Toast.makeText(ChatDetailActivity.this, "Message Sent", Toast.LENGTH_SHORT).show();
}
});
}
});
progressDialog.dismiss();
}
}
});
collectionReference.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException error) {
Toast.makeText(ChatDetailActivity.this, "Change", Toast.LENGTH_SHORT).show();
readMessage(userID, receiverID);
}
});
initNewRecycler();
}
private void initNewRecycler() {
recyclerView = binding.chatRecyclerView;
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.setStackFromEnd(false);
linearLayoutManager.setReverseLayout(true);
recyclerView.setLayoutManager(linearLayoutManager);
}
private void readMessage(String userID, String receiverID) {
mMessage = new ArrayList<>();
collectionReference.orderBy("timestamp", Query.Direction.DESCENDING).limit(limit)
.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
mMessage.clear();
for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots) {
MessageModel model = snapshot.toObject(MessageModel.class);
if (model.getReceiverID().equals(userID) && model.getSenderID().equals(receiverID)
|| model.getReceiverID().equals(receiverID) && model.getSenderID().equals(userID)) {
mMessage.add(model);
}
newMessageAdapter = new NewMessageAdapter(ChatDetailActivity.this, mMessage);
recyclerView.setAdapter(newMessageAdapter);
}
}
});
}
}
Firebase firestore database structure
Firebase-root
|
---- chats
|
---- userID
|
---messages
|
---receiverID
|
---messages
|
---- message: "Hello!"
|
---- timestamp: 1498472455940
|
---- senderID: senderID
|
---- receiverID: receiverID
Some sample screenshots of the problem I have been facing
The first screen is what appears when the chat activity is first opened and the messages are displayed. Here everything works fine and the messaging system works.
In the second picture however we can see that when the user scrolls up to see the previous messages, some of them are shown correctly but some of them like "Does it work" and "No perhaps" have different time and some are not in the correct order. This happens frequently whenever the user scrolls the list
This is the problem I have been facing for quite a while now. I am not sure what is causing this kind of behaviour and would love to have some light shed in this issue. If anyone can help, it would be highly appreciated. Thanks.
Facing an error.
I am making a chat application with firebase. where i am sending and printing the data from Firebase Realtime Database. the issue is that whenever i am adding or sending a data into the Firebase Realtime Database, its not only printing the currently added data but also printing the whole data from node Chats again and again wherever any data added into the Firebase Realtime Database.
how can i fix this?
Whats my think to solve the error?
I think removing of event listener which are being attached on call of
getMessage(); can fix the error.
This is my ChatActivity
package com.socialcodia.sherewatan;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import com.socialcodia.sherewatan.adapter.ChatAdapter;
import com.socialcodia.sherewatan.model.ChatModel;
import com.socialcodia.sherewatan.storage.Constants;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ChatActivity extends AppCompatActivity {
Toolbar toolbar;
private EditText inputMessage;
private ImageButton btnSendMessage;
private TextView toolbarUserName, toolbarUserStatus;
private ImageView toolbarUserImage;
//Firebase
FirebaseAuth firebaseAuth;
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseReference;
DatabaseReference chatDatabaseReference;
FirebaseUser firebaseUser;
RecyclerView chatRecyclerView;
Intent intent;
String toUid;
String myUid;
List<ChatModel> chatList;
ChatAdapter chatAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//init Chat Recycler View
chatRecyclerView = findViewById(R.id.chatRecyclerView);
//set layout manager at chatRecyclerview
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
chatRecyclerView.setLayoutManager(layoutManager);
//Firebase Init
firebaseAuth = FirebaseAuth.getInstance();
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference("Users");
chatDatabaseReference = firebaseDatabase.getReference("Chats");
firebaseUser =firebaseAuth.getCurrentUser();
//Init
inputMessage = findViewById(R.id.inputMessage);
btnSendMessage = findViewById(R.id.btnSendMessage);
toolbarUserName = findViewById(R.id.toolbarUserName);
toolbarUserStatus = findViewById(R.id.toolbarUserStatus);
toolbarUserImage = findViewById(R.id.toolbarUserImage);
toolbar = findViewById(R.id.chat_toolbar);
setSupportActionBar(toolbar);
intent = getIntent();
//Data From intent
toUid = intent.getStringExtra("uid");
//Click listener on btn send message
btnSendMessage.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
ValidateAndSendMessage();
}
});
getMessage();
}
private void ValidateAndSendMessage()
{
String message = inputMessage.getText().toString().trim();
if (message.isEmpty())
{
Toast.makeText(this, "Can't send empty message", Toast.LENGTH_SHORT).show();
}
else
{
sendMessage(message);
}
}
private void sendMessage(String message)
{
HashMap<String, Object> map = new HashMap<>();
map.put("msg",message);
map.put(Constants.TIMESTAMP,System.currentTimeMillis()/1000);
map.put("fromUid",myUid);
map.put("toUid",toUid);
DatabaseReference chatRef = firebaseDatabase.getReference("Chats");
chatRef.push().setValue(map);
inputMessage.setText("");
}
private void getMessage()
{
chatList = new ArrayList<>();
final DatabaseReference chatRef = firebaseDatabase.getReference("Chats");
chatRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren())
{
ChatModel chatModel = ds.getValue(ChatModel.class);
if (chatModel.getFromUid().equals(myUid) && chatModel.getToUid().equals(toUid) ||
chatModel.getFromUid().equals(toUid) && chatModel.getToUid().equals(myUid))
{
chatList.add(chatModel);
}
chatAdapter = new ChatAdapter(chatList,getApplicationContext());
chatAdapter.notifyDataSetChanged();
chatRecyclerView.setAdapter(chatAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
This is my ChatAdapter.class
package com.socialcodia.sherewatan.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.socialcodia.sherewatan.R;
import com.socialcodia.sherewatan.model.ChatModel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolder> {
List<ChatModel> modelClassList;
Context context;
private static final int MSG_TYPE_RIGHT = 0;
private static final int MSG_TYPE_LEFT = 1;
FirebaseUser firebaseUser;
public ChatAdapter(List<ChatModel> modelClassList, Context context) {
this.modelClassList = modelClassList;
this.context = context;
}
#NonNull
#Override
public ChatViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType==MSG_TYPE_RIGHT)
{
View view = LayoutInflater.from(context).inflate(R.layout.chat_right,parent,false);
ChatViewHolder viewHolder = new ChatViewHolder(view);
return viewHolder;
}
else
{
View view = LayoutInflater.from(context).inflate(R.layout.chat_left,parent,false);
ChatViewHolder viewHolder = new ChatViewHolder(view);
return viewHolder;
}
}
#Override
public void onBindViewHolder(#NonNull ChatViewHolder holder, int position) {
String msg = modelClassList.get(position).getMsg();
Long timestamp = modelClassList.get(position).getTimestamp();
holder.tvChatMessage.setText(msg);
holder.tvChatTime.setText(getTime(timestamp));
}
private String getTime(Long timestamp) {
Long ts = timestamp*1000;
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:a");
String time = sdf.format(new Date(ts));
return time;
}
#Override
public int getItemCount() {
return modelClassList.size();
}
#Override
public int getItemViewType(int position) {
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (modelClassList.get(position).getFromUid().equals(firebaseUser.getUid()))
{
return MSG_TYPE_RIGHT;
}
else
{
return MSG_TYPE_LEFT;
}
}
public class ChatViewHolder extends RecyclerView.ViewHolder
{
private TextView tvChatMessage, tvChatTime;
public ChatViewHolder(#NonNull View itemView) {
super(itemView);
tvChatMessage = itemView.findViewById(R.id.tvChatMessage);
tvChatTime = itemView.findViewById(R.id.tvChatTime);
}
}
}
This is my ChatModel.class
package com.socialcodia.sherewatan.model;
public class ChatModel {
public String fromUid, toUid, msg;
Long timestamp;
public ChatModel() {
}
public ChatModel(String fromUid, String toUid, String msg, Long timestamp) {
this.fromUid = fromUid;
this.toUid = toUid;
this.msg = msg;
this.timestamp = timestamp;
}
public String getFromUid() {
return fromUid;
}
public void setFromUid(String fromUid) {
this.fromUid = fromUid;
}
public String getToUid() {
return toUid;
}
public void setToUid(String toUid) {
this.toUid = toUid;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
You forgot to clear the modelClassList.
private void getMessage()
{
chatList = new ArrayList<>();
final DatabaseReference chatRef = firebaseDatabase.getReference("Chats");
chatRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
chatList.clear(); // Clear list
for (DataSnapshot ds : dataSnapshot.getChildren())
{
ChatModel chatModel = ds.getValue(ChatModel.class);
if (chatModel.getFromUid().equals(myUid) && chatModel.getToUid().equals(toUid) ||
chatModel.getFromUid().equals(toUid) && chatModel.getToUid().equals(myUid))
{
chatList.add(chatModel);
}
chatAdapter = new ChatAdapter(chatList,getApplicationContext());
chatAdapter.notifyDataSetChanged();
chatRecyclerView.setAdapter(chatAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
That will clear the list as well fix your problem.
Declare HashMap or ArrayList globally and write this code map.clear() or arrayList.clear() at the very beginning of the method from which you are retreiving your data. Hopefully the problem will be solved.
I have orders collection in firestore:
And I have Sellers collection and inside Sellers collection have another Fruits collection :
I want to get data in orders collection only orders collection fruit_ID equals Sellers/Fruits collection Document ID and add into recyclerview
Is it possible?
Activity class:
package com.example.freshbucket.Seller;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.widget.Toast;
import com.example.freshbucket.Adapter.OrdersSellerRecylerAdapter;
import com.example.freshbucket.Model.PlaceOrder;
import com.example.freshbucket.R;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QuerySnapshot;
import javax.annotation.Nullable;
import static android.support.constraint.Constraints.TAG;
public class SellerGetOrdersActivity extends AppCompatActivity {
String fid, pro;
private FirebaseAuth mAuth = FirebaseAuth.getInstance();
String user_id = mAuth.getCurrentUser().getUid();
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference orders = db.collection("Orders");
private CollectionReference sellers = db.collection("Sellers/"+user_id+"/Fruits");
private OrdersSellerRecylerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seller_get_orders);
setupRecyclerView();
}
private void setupRecyclerView()
{
Query query =orders.orderBy("timestamp", Query.Direction.DESCENDING).whereEqualTo("fruit_ID",fid);
FirestoreRecyclerOptions<PlaceOrder> options = new FirestoreRecyclerOptions.Builder<PlaceOrder>().setQuery(query, PlaceOrder.class).build();
adapter = new OrdersSellerRecylerAdapter(options);
RecyclerView recyclerView = findViewById(R.id.ordersReView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
//swipe delete
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT| ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
adapter.deleteItem(viewHolder.getAdapterPosition());
}
}).attachToRecyclerView(recyclerView);
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
sellers.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.d(TAG, "Error:" + e.getMessage());
} else {
for (DocumentSnapshot doc :queryDocumentSnapshots){
fid = doc.getId();
// pro = doc.getString("province");
// fid = doc.getString("fruit_ID");
Toast.makeText(SellerGetOrdersActivity.this, "Register error:" +fid , Toast.LENGTH_SHORT).show();
}
}
}
});
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
}
Adapter:
package com.example.freshbucket.Adapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import com.example.freshbucket.Model.PlaceOrder;
import com.example.freshbucket.R;
import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
public class OrdersSellerRecylerAdapter extends FirestoreRecyclerAdapter<PlaceOrder, OrdersSellerRecylerAdapter.OrdersSellerHolder> {
Context context;
public OrdersSellerRecylerAdapter(#NonNull FirestoreRecyclerOptions<PlaceOrder> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull final OrdersSellerHolder holder, int position, #NonNull final PlaceOrder model) {
holder.txtfruitname.setText(model.getName());
holder.txtqun.setText(model.getQun());
holder.txtcusname.setText(model.getCustomer_Name());
holder.txtaddress1.setText(model.getAddressLine1());
holder.txtaddress2.setText(model.getAddressLine2());
holder.txtcity.setText(model.getCity());
}
#NonNull
#Override
public OrdersSellerHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.order_list_item_seller,viewGroup, false);
context = viewGroup.getContext();
return new OrdersSellerHolder(v);
}
class OrdersSellerHolder extends RecyclerView.ViewHolder{
TextView txtfruitname, txtqun, txtcusname, txtaddress1, txtaddress2, txtcity;
EditText tctBprice;
public OrdersSellerHolder(#NonNull View itemView) {
super(itemView);
txtfruitname = itemView.findViewById(R.id.fruitnametext);
txtqun = itemView.findViewById(R.id.fruitquntext);
txtcusname = itemView.findViewById(R.id.cusnametext);
txtaddress1 = itemView.findViewById(R.id.addres1text);
txtaddress2 = itemView.findViewById(R.id.addres2text);
txtcity = itemView.findViewById(R.id.citytext);
}
}
public void deleteItem(int position) {
getSnapshots().getSnapshot(position).getReference().delete();
}
}
I want to get data in orders collection only orders collection
fruit_ID
OK, you want to get fruit_ID?
equals Sellers/Fruits collection Document ID and add into recyclerview
and you want to get fruit_ID, which equals with Sellers/Fruits ?
like if (fruit_ID.equals(sellerFruits_ID) {// get fruit_ID}
I will try to answer it.
PROBLEM
1. you as a seller and have your seller uid in your Sellers collection and want to get V4x1Dh..
2. You have buyer uid in your Orders collection and want to get 83Fmf..
3. You want to get Banana in Sellers/Fruits, which the Banana as id.
Lastly, you want to load datas of Sellers/Fruits into recyclerView because
you want to get data in orders collection only orders collection
fruit_ID
ANSWER
Answer number one: Please retrieve the Sellers ids and get V4x1Dh based ViewHolder position that I will explain later.
Answer number two: Please retrieve the Orders ids and get 83Fmf based ViewHolder position that I will explain later.
Answer number two: Please retrieve the Sellers Fruits ids let's say sellerFruit_ID and get Banana based ViewHolder position that I will explain later. NOTE: Since Banana in document it will be id.
DETAILS:
Retrieving the Sellers ids and get V4x1Dh:
firebaseFirestore
.collection("Sellers")
.addSnapshotListener(new EventListener<QuerySnapshot>(){
#Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e){
for (DocumentChange doc : documentSnapshots.getDocumentChanges()){
if (doc.getType() == DocumentChange.Type.ADDED){
// RETRIEVING Orders id
String orders_ID = doc.getDocument().getId();
YourContentOrdersHere contentOrders = doc.getDocument().toObject(YourContentOrdersHere.class).withId(orders_ID);
// RETRIEVING Sellers id
String sellers_ID = doc.getDocument().getId();
YourContentSellersHere contentSellers = doc.getDocument().toObject(YourContentSellersHere.class).withId(sellers_ID);
contentListOrders.add(contentOrders); //example: List<YourContentOrdersHere> contentList
adapter.notifyDataSetChanged(); // before of course, you add this in onCreate adapterOrders = new YourAdapterOrders(contentListOrders);
contentListSellers.add(contents); //example: List<YourContentSellersHere> contentList
adapter.notifyDataSetChanged(); // before of course, you add this in onCreate adapterSellers = new YourAdapterSellers(contentListSellers);
}
}
}
});
make sure your content class extends the ids
public class YourContentOrdersHere extends OrdersId {
// make your constructor here of course
// make your getter to get id
}
and make OrdersId.class
public class OrdersId{
#Exclude
public String OrdersId;
public <T extends OrdersId> T withId(#NonNull final String id) {
this.OrdersId = id;
return (T) this;
}
}
and last one , from your adapter class retrieving OrdersId. As Example:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// GET YOUR `Sellers` id based position and getSellerId() from getter of your content class
String sellers_ID = contentListSeller.get(position).getSellerId(); // don't forget List<YourContentSellers> contentList = new ArrayList<>();
firebaseFirestore
.collection("Sellers")
.document(sellers_ID)
.collection("Fruits")
.document("Banana")
// STORE 'LIKE TAP' USING LIKE BUTTON
holder.likeHome.seOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
/* RETRIEVING VALUE UNDER currentUserId */
firebaseFirestore.collection("Posts/" + postId + "/Likes").document(currentUserId).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>(){
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task){
if (!task.getResult().exists()) {
/* STORE NEW VALUE */
Map<String, Object> likesMap = new HashMap<>();
likesMap.put("timestamp", FieldValue.serverTimestamp);
firebaseFirestore.collection("Posts/" + postId + "/Likes").document(currentUserId).set(likesMap);
} else {
// retrieve like timestamp
String whenToLike = task.getResult().getString("timestamp");
holder.setWhenToLike(whenToLike);
/* DELETE VALUE */
firebaseFirestore.collection("Posts/" + postId + "/Likes").document(currentUserId).delete();
}
}
});
}
});
}
I want to add a button for each item in the Firebase recycler view.
I've created the button, it's being showed, and i'm receiving the Toast when I press it.
But - How can I get the relevant item on it's list ?
For example - When I press the 'DELETE' I want to delete that certain mission 'aspodm'. (Sorry for the large picture, how do I make it smaller?)
This is how the database looks like (vfPvsk... is the user id, and 773f... is random uuid for mission id):
And that is the code of the relevant fragment. (The Toast when clicking the button is activated - I just don't know how to get to the relevant mission in order to delete it)
package com.airpal.yonatan.airpal;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
/**
* A simple {#link Fragment} subclass.
*/
public class PendingFragment_User extends Fragment {
private String TAG = "dDEBUG";
private RecyclerView mPendingList;
private DatabaseReference mMissionsDb;
private FirebaseAuth mAuth;
private String mCurrent_user_id;
private View mMainView;
Query queries;
public PendingFragment_User() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mMainView = inflater.inflate(R.layout.fragment_pending_user, container, false);
mPendingList = (RecyclerView)mMainView.findViewById(R.id.pending_recycler_user);
mAuth = FirebaseAuth.getInstance();
mCurrent_user_id = mAuth.getCurrentUser().getUid();
mMissionsDb = FirebaseDatabase.getInstance().getReference().child("Missions").child(mCurrent_user_id);
queries = mMissionsDb.orderByChild("status").equalTo("Available");
mMissionsDb.keepSynced(true);
mPendingList.setHasFixedSize(true);
mPendingList.setLayoutManager(new LinearLayoutManager(getContext()));
// Inflate the layout for this fragment
return mMainView;
}
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Mission, PendingFragment_User.MissionsViewHolder> firebaseMissionsUserRecyclerAdapter = new FirebaseRecyclerAdapter<Mission, PendingFragment_User.MissionsViewHolder>(
Mission.class,
R.layout.missions_single_layout,
PendingFragment_User.MissionsViewHolder.class,
queries
) {
#Override
protected void populateViewHolder(PendingFragment_User.MissionsViewHolder missionViewHolder, final Mission missionModel, int missionPosition) {
// Log.d(TAG, "inside populateViewHolder" + missionModel.getType() + " , " + missionModel.getDescription());
missionViewHolder.setMissionName(missionModel.getType());
missionViewHolder.setMissionDescription(missionModel.getDescription());
missionViewHolder.setMissionStatus(missionModel.getStatus());
missionViewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Toast.makeText(view.getContext(), "esto es un boton"+ view.getNextFocusUpId(), Toast.LENGTH_SHORT).show();
Log.d(TAG,"The button was pressed");
}
});
}
};
mPendingList.setAdapter(firebaseMissionsUserRecyclerAdapter);
}
public static class MissionsViewHolder extends RecyclerView.ViewHolder {
View mView;
Button button ;
public MissionsViewHolder(View itemView) {
super(itemView);
mView = itemView;
button = (Button)mView.findViewById(R.id.pending_single_button);
}
public void setMissionName(String name){
TextView mMissionNameView = mView.findViewById(R.id.mission_single_name);
mMissionNameView.setText(name);
}
public void setMissionStatus(String status){
TextView mMissionStatusView = mView.findViewById(R.id.mission_single_status);
mMissionStatusView.setText(status);
if (status.equals("Available")){
mMissionStatusView.setTextColor(Color.parseColor("#008000"));;
} else {
mMissionStatusView.setTextColor(Color.parseColor("#FF0000"));;
}
}
public void setMissionDescription(String description){
TextView mMissionDescriptionView = mView.findViewById(R.id.mission_single_description);
mMissionDescriptionView.setText(description);
}
}
}
Try using a subclass rather than anonymous one. Then, you'll be able to access the getItem(int position) method of the adapter. Something along the lines of:
private class MissionAdapter extends FirebaseRecyclerAdapter<Mission, PendingFragment_User.MissionsViewHolder> {
public MissionAdapter(Query queries){
super(Mission.class, R.layout.missions_single_layout, PendingFragment_User.MissionsViewHolder.class, queries);
}
#Override
protected void populateViewHolder(PendingFragment_User.MissionsViewHolder missionViewHolder, final Mission missionModel, final int missionPosition) {
Log.d(TAG, "inside populateViewHolder" + missionModel.getType() + " , " + missionModel.getDescription());
missionViewHolder.setMissionName(missionModel.getType());
missionViewHolder.setMissionDescription(missionModel.getDescription());
missionViewHolder.setMissionStatus(missionModel.getStatus());
missionViewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Mission clickedMission = MissionAdapter.this.getItem(missionPosition);
if (clickedMission != null){ // for the sake of being extra-safe
Log.d(TAG,"The button was pressed for mission: " + clickedMission.getType());
}
}
});
}
}
I made it print a log, but you should be able to do anything you want with the retrieved Mission object in there.