In this project I have two types of users (teacher and students). Teacher can add classes and student should be able to choose class and sign in to class, when student is signed in class the teacher should be able to give him a grade. I don't know how to connect user to a class and give him grades.
this is my classesAdapter
public class ClassesAdapter extends FirebaseRecyclerAdapter<Classes, ClassesAdapter.StudentViewHolder> {
/**
* Initialize a {#link RecyclerView.Adapter} that listens to a Firebase query. See
* {#link FirebaseRecyclerOptions} for configuration options.
*
* #param options
*/
public ClassesAdapter(#NonNull FirebaseRecyclerOptions options) {
super(options);
}
protected void onBindViewHolder(#NonNull StudentViewHolder holder, int position, #NonNull Classes model) {
holder.className.setText(model.getCname());
holder.classInfo.setText(model.getDescription());
holder.classUid.setText(model.getUid());
String keyId = this.getRef(position).getKey();
}
#NonNull
#Override
public StudentViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.classes, parent, false);
return new ClassesAdapter.StudentViewHolder(view);
}
public class StudentViewHolder extends RecyclerView.ViewHolder {
TextView className;
TextView classInfo;
TextView classUid;
Button classSignInBtn;
public StudentViewHolder(#NonNull View itemView) {
super(itemView);
className = itemView.findViewById(R.id.classNameTxt);
classInfo = itemView.findViewById(R.id.classInfoTxt);
classUid = itemView.findViewById(R.id.classUidTxt);
classSignInBtn = itemView.findViewById(R.id.classSignInBtn);
int position = getAdapterPosition();
classSignInBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
String uId = mAuth.getCurrentUser().getUid();
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference ref = db.getReference("ednevnik/korisnici/" + uId);
DatabaseReference ref1 = db.getReference("ednevnik/razredi/");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String name = snapshot.child("name").getValue().toString();
String email = snapshot.child("email").getValue().toString();
String grade = " ";
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
}
}
}
Welcome to the StackOverflow. Well, I have a similar issue with the real-time database. The issue with this type of database is that it is foresight for fast and response in real-time, which means that this type of database is for chat applications, and generally for response in real-time. My suggestion is to migrate your data to the Cloud Firestore database which is for this kind of application, I had a similar issue.
Here is the documentation for the Cloud Firestore database for Android:
https://firebase.google.com/docs/firestore
Practically, this function is an issue:
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String name = snapshot.child("name").getValue().toString();
String email = snapshot.child("email").getValue().toString();
String grade = " ";
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
You are retrieving data when data is changing inside the database, and that event is not going to happen. That's why I am suggesting the Cloud Firestore database.
I guess that this helps you.
Best Regards,
Sanady
Related
I am attempting to load an undetermined number of viewHolders into a recyclerView with data retrieved from the Firebase Realtime Database. This is for a messaging component of my Android app. I am first iterating through a list of chat keys (see "Chat Keys" node below) stored in the database under the current user's userID. For each key, I access the specific associated chat (see "Chat Basics" node below). For testing purposes, I am only retrieving and setting one value type ("lastMessage"), however I intend to set multiple values per viewHolder after successful testing. I am unsure about how to correctly pass the data stored in my model class for each iteration to my onBindViewHolder in my adapter class for display in individual viewholders.
I have had success in retrieving "lastMessage" for each iteration in my fragment class, then passing a string to my adapter class for each iteration. The viewHolders did display the correct string values. Though I can do this successfully, I need to be able to pass an arrayList of data for each iteration, so that I am not limited to only passing a single value per key. Because the onBindViewHolder in the adapter class is position dependent, it is my understanding that I cannot simply pass an array list with simple strings, but should instead pass an instance (O.O.C -might not be the right word) of the model class in an arrayList to be further accessed in the adapter class.
One way or another, please help me load a set of values into an undetermined number of viewHolders for each Firebase Database chat key iteration based on the code provided below. Cheers.
Model Class:
public class MessagesList {
private String lastMessage;
//Default constructor
public MessagesList() {
}
public MessagesList(String lastMessage) {//String userName,, String profileImage) {
//this.userName = userName;
this.lastMessage = lastMessage;
//this.profileImage = profileImage;
}
public String getLastMessage() {
return lastMessage;
}
public void setLastMessage(String lastMessage) {
this.lastMessage = lastMessage;
}
}
Adapter Class:
public class TestRecyclerViewAdapter extends RecyclerView.Adapter<TestRecyclerViewAdapter.ViewHolder> {
private ItemClickListener mClickListener;
private LayoutInflater mInflater;
private ArrayList<MessagesList> mList;
//Data is passed into the constructor
public TestRecyclerViewAdapter(Context context, ArrayList<MessagesList> messagesList) {
this.mInflater = LayoutInflater.from(context);
this.mList = messagesList;
}
//Inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.standard_chat_list_layout, parent, false);
return new ViewHolder(view);
}
//Binds the data to the TextView in each row
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.chatListLastMessage.setText(mList.get(position).getLastMessage());
}
//Total number of rows
#Override
public int getItemCount() {
return 0;
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView chatListLastMessage;
ViewHolder(View itemView) {
super(itemView);
chatListLastMessage = itemView.findViewById(R.id.chatListLastMessage);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
Relevant Fragment:
public class MessagingFragment1 extends Fragment {
private DatabaseReference databaseReference;//, personalChatReference;
private RecyclerView directMessageRecycler;
private String currentUserID;
private TestRecyclerViewAdapter adapter;
private ArrayList<MessagesList> list_of_groups = new ArrayList<>();
public MessagingFragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_messaging1, container, false);
currentUserID = FirebaseAuth.getInstance().getCurrentUser().getUid();
databaseReference = FirebaseDatabase.getInstance().getReference();
directMessageRecycler = rootView.findViewById(R.id.directMessageRecycler);
//directMessageRecycler.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
directMessageRecycler.setLayoutManager(linearLayoutManager);
//get a reference to the join table mentioned above
databaseReference.child("Chat Keys").child(currentUserID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
String groupId = (snapshot.getKey());
databaseReference.child("Chat Basics").child(groupId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshotInner) {
MessagesList messagesList = dataSnapshotInner.getValue(MessagesList.class);
list_of_groups.add(messagesList);
adapter = new TestRecyclerViewAdapter(getActivity(), list_of_groups);
directMessageRecycler.setAdapter(adapter);
//adapter.setClickListener();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return rootView;
}
Database Structure (x2):
Turns out I just forgot to return the correct item count
//Total number of rows
#Override
public int getItemCount() {
return mList.size();
}
and the result was a blank recyclerView. Despite the stupid reason for having posted this question, I will leave it as an example for others (like me) who've had difficulty finding a concise, full example of how to retrieve data from Firebase Database using simple key identifiers in one node to find the core data in another node.
So i have a recycler view that is designed to show users sending messages to each other from my Firebase RTD. Originally it was working to show all users and the recycler items were clicked then it would show messages between the users. However, when modifying it to only view users that were in open messages with the current user, the items that populated my recycler view no longer displays and an error saying E/RecyclerView: No adapter attached; skipping layout is logged within the Run tab.
Unfortunately i can no longer undo the changes and have struggled to find the cause of my problem but have assume that it is either taking place in my adapted or activity classes.
InboxActivity.java:
public class InboxActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<User> inboxLst;
FirebaseUser user;
DatabaseReference reference;
UserAdapter usrAdpt;
private List<String> userLst;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inbox);
//Identify and setup recycler view
recyclerView = findViewById(R.id.rycInbox);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
userLst = new ArrayList<>();
//Get all chats between current user and and other users
user = FirebaseAuth.getInstance().getCurrentUser();
reference = FirebaseDatabase.getInstance().getReference("Chats");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
userLst.clear();
for (DataSnapshot snp : dataSnapshot.getChildren()){
Chat chat = snp.getValue(Chat.class);
if (chat.getSender().equals(user.getUid())){
userLst.add(chat.getReceiver());
}
if (chat.getReceiver().equals(user.getUid())){
userLst.add(chat.getSender());
}
}
readChat();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void readChat() {
inboxLst = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("Users");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
userLst.clear();
for (DataSnapshot snp : dataSnapshot.getChildren()) {
User usr = snp.getValue(User.class);
//Display users that are currently in an open chat
for (String id : userLst){
if(usr.getId().equals(id)){
if(inboxLst.size() != 0){
for (User usrl : inboxLst){
if(!usr.getId().equals(usrl.getId())){
inboxLst.add(usr);
}
}
}else{
inboxLst.add(usr);
}
}
}
}
//Set the adapter for the recycler view once using the chat information retrieved from firebase database
usrAdpt = new UserAdapter(InboxActivity.this,inboxLst);
recyclerView.setAdapter(usrAdpt);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { }
});
}
}
UserAdapter.java:
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {
private Context cont;
private List<User> nUser;
public UserAdapter(Context cont, List<User> nUser){
this.cont = cont;
this.nUser = nUser;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(cont).inflate(R.layout.lst_layout_inbox, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
User user = nUser.get(position);
holder.username.setText(user.getUsername());
holder.usrLst.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(cont, MessageActivity.class);
intent.putExtra("userid",user.getId());
cont.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return nUser.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView username;
RelativeLayout usrLst;
public ViewHolder(View itemView){
super(itemView);
username = itemView.findViewById(R.id.usrName);
usrLst = itemView.findViewById(R.id.usrCard);
}
}
}
The only catchup in your question is, in the following method:
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
userLst.clear(); // <------ WHY YOU CLEAR LIST HERE??? COMMENT THIS ----------
for (DataSnapshot snp : dataSnapshot.getChildren()) {
User usr = snp.getValue(User.class);
//Display users that are currently in an open chat
for (String id : userLst){
if(usr.getId().equals(id)){
if(inboxLst.size() != 0){
for (User usrl : inboxLst){
if(!usr.getId().equals(usrl.getId())){
inboxLst.add(usr);
}
}
}else{
inboxLst.add(usr);
}
}
}
}
//Set the adapter for the recycler view once using the chat information retrieved from firebase database
usrAdpt = new UserAdapter(InboxActivity.this,inboxLst);
recyclerView.setAdapter(usrAdpt);
}
why you do userLst.clear(); ?
Since in OnCreate() method you populate userLst and call readChat(). And in onDataChange() you clear the userLst and then afterwards you try to iterate over the userLst to Display users that are currently in an open chat.
I would suggest to comment this userLst.clear(); and after setting items call notifyDataSetChanged()
Try these things:
Set the adapter in onCreate.
and in the onDataChanged listener, update the ArrayList and call notifyDataSetChanged().
This should help
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm having some particular problems with my android project.
In particular I have two collections, Users and Courses:
the first one comprehend the list of users (teachers) which have two Strings (email and idCourse)
in the second one there is the list of courses, each one relating to a user (idCourse is the same of the user), inside each course there is a list of lesson which i need to access with a specific user.
I saved in an object admin its data to access to a specific Lessons collection, because in the path there is the admin id.
Courses path to Lessons
Users collection
I tried to, but when i save the id in the addCompleteListener method the data get lost outside, indeed in the addSnapshotListener the value of admin.getCourseId() is null so my recyclerView results empty.
If I try to copy the second method in the first one, as soon as I save the idCourse in Admin, the method works, but if I click on the lesson when i use the app, the app crashes.
I know this may be a specifical issue of mine, but i would like to hear something from you about it.
I'm posting my android project too.
Android Project on Google Drive
Thanks in advance for your help!
CLASS LezioniDocenteActivity:
public class LezioniDocenteActivity extends AppCompatActivity {
private static final String TAG = "FireLog";
private RecyclerView mMainList;
private FirebaseFirestore mFirestore;
private FirebaseAuth firebaseAuth;
private LessonsListAdapter lessonsListAdapter;
private List<Lesson> lessonList;
private String course_id;
//admin per memorizzare le info
private final User admin = new User();
#Override
public void onBackPressed(){
startActivity(new Intent(LezioniDocenteActivity.this, DocenteActivity.class));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lezioni_docente);
lessonList = new ArrayList<>();
lessonsListAdapter = new LessonsListAdapter(lessonList, getApplicationContext());
mMainList = (RecyclerView)findViewById(R.id.lesson_list);
mMainList.setHasFixedSize(true);
mMainList.setLayoutManager(new LinearLayoutManager(this));
mMainList.setAdapter(lessonsListAdapter);
firebaseAuth = FirebaseAuth.getInstance();
//utente in uso corrente
final FirebaseUser user = firebaseAuth.getCurrentUser();
admin.setEmail(user.getEmail());
mFirestore = FirebaseFirestore.getInstance();
mFirestore.collection("Users").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
boolean find = false;
for (DocumentSnapshot doc : task.getResult()) {
String email = doc.getString("email");
if (email.equals(admin.getEmail())) {
//getting admin's courseID
admin.setCourseId(doc.getString("idCorso"));
break;
}
}
}
});
mFirestore.collection("Courses /" + admin.getCourseId() + "/Lessons").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot documentSnapshots, #Nullable FirebaseFirestoreException e) {
if(e!=null){
Log.d(TAG, "Error :" + e.getMessage());
return;
}
for(DocumentChange doc : documentSnapshots.getDocumentChanges()){
if(doc.getType() == DocumentChange.Type.ADDED){
Lesson lesson = doc.getDocument().toObject(Lesson.class);
lessonList.add(lesson);
lessonsListAdapter.notifyDataSetChanged();
}
}
}
});
}
}
CLASS LessonListAdapter:
public class LessonsListAdapter extends RecyclerView.Adapter<LessonsListAdapter.ViewHolder> {
public List<Lesson> lessonList;
public Context context;
final User admin = new User();
public LessonsListAdapter(List<Lesson> lessonList, Context context){
this.lessonList = lessonList;
this.context = this.context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_lessons, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
final FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
final FirebaseUser user = firebaseAuth.getCurrentUser();
admin.setEmail(user.getEmail());
holder.dayText.setText(lessonList.get(position).getLessonDate());
holder.argText.setText(lessonList.get(position).getArgument());
final String lessID = lessonList.get(position).lessonID;
final int i = position;
firebaseFirestore.collection("Users").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
boolean find = false;
for(DocumentSnapshot doc : task.getResult()){
String email = doc.getString("email");
if(email.equals(admin.getEmail())) {
find = true;
//getting admin's courseID
admin.setCourseId(doc.getString("courseId"));
break;
}
}
if (find){
holder.delete.setVisibility(View.VISIBLE);
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "OnClick funziona", Toast.LENGTH_SHORT).show();
}
});
} else holder.delete.setVisibility(View.GONE);
}
});
}
#Override
public int getItemCount() {
return lessonList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
View mView;
public TextView dayText;
public TextView argText;
public ImageView delete;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mView = itemView;
dayText = (TextView) mView.findViewById(R.id.day_text);
argText = (TextView) mView.findViewById(R.id.arg_text);
delete = (ImageView) mView.findViewById(R.id.ic_delete);
}
}
}
The following code will work for you. But you have to make changes according to it. I am not using Android Studio. It's notepad code.
mfirebaseFirestore.collection("Users").orderBy("email")
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
for (QueryDocumentSnapshot querySnapshot : task.getResult()){
if (querySnapshot.get("email").equals(user.getEmail())){
mfirebaseFirestore.collection("Courses/"+ querySnapshot.get("idCorso")+"/Lessons")
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot documentSnapshots, #Nullable FirebaseFirestoreException e) {
for(DocumentChange doc : documentSnapshots.getDocumentChanges()){
if(doc.getType() == DocumentChange.Type.ADDED){
Lesson lesson = doc.getDocument().toObject(Lesson.class);
lessonList.add(lesson);
}
lessonsListAdapter = new LessonsListAdapter(lessonList, getApplicationContext());
lessonsListAdapter.notifyDataSetChanged();
}
}
});
}
}
}
});
Explanation about code :
From above code as everyone explained Firebase calls are asynchronous (e.g. answer). So the data your trying to retrieve is receiving null as you said.
The above code will check in your database about email then retrieve the details of that user. Which means you will get the course id from it. Then directly call the function to retrieve lessons list by passing the course id.
I have a chat app as part of my Android app that stores all messages in a chat room under a Firebase database reference that carries the ID number for that room. As it stands, the RecyclerView that holds the messages in the chat Activity downloads all messages in that room whenever the user enters it, consuming a potentially unwieldy amount of data. How should I go about making it only download the X most recent messages and download X more if the user scrolls to top?
Here is my adapter:
public class ChatRecyclerViewAdapter extends RecyclerView.Adapter<ChatRecyclerViewAdapter.ViewHolder> {
private static final String TAG = "ChatRecyclerViewAdapter";
private String mRoomID;
private Context mContext;
private DatabaseReference mDatabaseReference;
private ArrayList<Message> messageList;
private ChildEventListener mListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
// Convert data snapshot from Database into a Message Object
Message message = dataSnapshot.getValue(Message.class);
// Add it to an arrayList of Messages
messageList.add(message);
// Notice Changes
notifyItemInserted(messageList.size());
}
#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) {
}
};
public ChatRecyclerViewAdapter(Context mContext, ArrayList<String> mMessage, ArrayList<String> mAuthor, String mRoomID, DatabaseReference reference) {
this.mContext = mContext;
this.mRoomID = mRoomID;
messageList = new ArrayList<>();
mDatabaseReference = reference.child(mRoomID+"_messages");
mDatabaseReference.addChildEventListener(mListener);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//This method loads layout(fields) of ViewHolder
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_msg_row,parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
// This method fills fields with data for each list item
Log.d(TAG,"onBindViewHolder called");
Message message = messageList.get(position);
holder.message.setText(message.getMessage());
holder.author.setText(message.getAuthor()+":");
}
#Override
public int getItemCount() {
return messageList.size();
}
//Viewholder stores the information about the layout and content of each list item, and serves as a template for each item of a RecyclerView
public class ViewHolder extends RecyclerView.ViewHolder {
TextView author;
TextView message;
RelativeLayout singleMessageContainer;
public ViewHolder(View itemView) {
super(itemView);
author = itemView.findViewById(R.id.chatAuthor);
message = itemView.findViewById(R.id.chatMessage);
singleMessageContainer = itemView.findViewById(R.id.singleMessageContainer);
}
}
void cleanup() {
mDatabaseReference.removeEventListener(mListener);
}
}
If the messages are stored chronologically already (e.g. if you use push() to add them), you can order the messages by their key and get the most recent ones with:
mDatabaseReference = reference.child(mRoomID+"_messages");
Query recentMessages = mDatabaseReference.orderByKey().limitToLast(10);
recentMessages.addChildEventListener(mListener);
As Doug commented, please check the Firebase documentation on queries for more options
How do I query SQL IN clause in Firebase Android? I want to use it in a Firebase Recycler adapter to retrieve only some children based on some condition. Something like the following statement:
SQL----> select * from posts where city in(10 cities comes here)
I need a Firebase query to use that in the Firebase Recycler adapter.
The Firebase database does not have the equivalent of SQL's WHERE id IN (1,2,3). In the case of selecting by ID, Firebase's way of retrieving items is equally fast because Firebase pipelines the requests.
Your case is different though, since you're not selecting by ID. Unfortunately there is no way to directly map your query to a equivalent on the Firebase Database.
Instead of trying to make Firebase's NoSQL database do SQL tricks, I highly recommend that you start mapping your data model to something that fits better with a NoSQL database. Some great resources to kick start this process are this article on NoSQL data modeling and our new video series on Firebase for SQL developers.
Also see Firebase complex "contain" queries
I found the solution: we cannot use FirebaseRecyclerAdapter. Instead we have to create custom adapter that extends RecyclerView.ViewHolder.
For passing values to this adapter, first we have to retrieve data using addValueEventListener and then we have to pass values to our adapter.
This is my code...
final ArrayList<Timeline> timelines = new ArrayList<>();
mDatabaseTimeline.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
final Timeline timeline = dataSnapshot.getValue(Timeline.class);
if(timeline != null){
mDatabaseFriends.child(mAuth.getCurrentUser().getUid()).child("active").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (mAuth.getCurrentUser().getUid().equals(timeline.getUid()) || dataSnapshot.hasChild(timeline.getUid())) {
timelines.add(timeline);
mTimelineRecycler.setAdapter(new RecyclerAdapter(TimelineFragment.this.getContext(), timelines));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#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) {
}
});
adapter----->
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
ArrayList<Timeline> timeline;
public RecyclerAdapter(Context context, ArrayList<Timeline> timeline) {
this.context = context;
this.timeline = timeline;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View row = inflater.inflate(R.layout.timeline_row, parent, false);
TimelineViewHolder holder = new TimelineViewHolder(row);
return holder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final String post_key = timeline.get(position).getPostkey();
((TimelineViewHolder) holder).setUsername(timeline.get(position).getUsername());
}
#Override
public int getItemCount() {
return timeline.size();
}
public class TimelineViewHolder extends RecyclerView.ViewHolder {
public TimelineViewHolder(View itemView) {
super(itemView);
view = itemView;
}
public View getView() {
return view;
}
public void setUsername(String username) {
TextView usernameTxtView = (TextView) view.findViewById(R.id.timeline_username);
usernameTxtView.setText(username);
}
}
}