I'm working on an app for a club where members attendance should be recorded. I'm having trouble getting it properly in a list view.
Here is a portion of the database:
There might be more than one sport attended like Karate or swimming for a given day. I want to get the member's attendance in a list view. I'll try to section it by day later, but for now I need to get the data properly.
Here is the model I made:
public class MemberAttendance {
private String day;
private HashMap<String, Object> attendedSport;
public MemberAttendance() {
}
public MemberAttendance(String day, HashMap<String, Object> attendedSport) {
this.day = day;
this.attendedSport = attendedSport;
}
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public HashMap<String, Object> getAttendedSport() {
return attendedSport;
}
public void setAttendedSport(HashMap<String, Object> attendedSport) {
this.attendedSport = attendedSport;
}
}
Here is the adapter:
public class MemberAttendanceAdapter extends FirebaseListAdapter<MemberAttendance> {
public MemberAttendanceAdapter(Activity activity, Class<MemberAttendance> modelClass, int modelLayout, Query ref) {
super(activity, modelClass, modelLayout, ref);
}
#Override
protected void populateView(View view, MemberAttendance memberAttendance, int i) {
// Get values from firebase database
String day = memberAttendance.getDay();
HashMap<String, Object> hashMap = memberAttendance.getAttendedSport();
String sport = (String) hashMap.get("attended");
String date = (String) hashMap.get("timestamp");
// Create views and assign values
TextView dayTxtView = (TextView) view.findViewById(R.id.dayTxtView);
dayTxtView.setText(day);
TextView sportTxtView = (TextView) view.findViewById(R.id.sportTxtView);
sportTxtView.setText(sport);
TextView dateTxtView = (TextView) view.findViewById(R.id.dateTxtView);
dateTxtView.setText(date);
}
}
And here how I try to set the adapter:
final FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference attendanceRef = database.getReference()
.child(Constants.MEMBERS_NODE).child(userID).child("attendance");
attendanceAdapter = new MemberAttendanceAdapter(getActivity(), MemberAttendance.class,
R.layout.attendance_list_item, attendanceRef);
attendanceListView.setAdapter(attendanceAdapter);
So far not working and gives null pointer exception on the object reference that uses HashMap.get(..)
String sport = (String) hashMap.get("attended");
Any help is appreciated.
You might want to restructure your NoSQL Database like this:
member
---memberID
------attendance
---------attendance ID
------------attended
------------timestamp
------------date
For example:
member
---member1
------attendance
---------attendance1
------------soccer
------------14938372834
------------14-04-2017
---------attendance2
------------swimming
------------14938374323
------------14-04-2017
You don't need to store the date because use could use the timestamp to create a Date object in Java that would contain that information
Date date = new Date(timestamp);
With this structure you would need to change your POJO to this:
public class MemberAttendance {
private String attended;
private long timestamp;
public MemberAttendance() {
}
public MemberAttendance(String attended, long timestamp) {
this.attended = attended;
this.timestamp = timestamp;
}
public String getAttended() {
return attended;
}
public void setAttended(String attended) {
this.attended = attended;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.attendedSport = attendedSport;
}
}
And then you could use your same Firebase Query with the following changes in the adapter:
public class MemberAttendanceAdapter extends FirebaseListAdapter<MemberAttendance> {
public MemberAttendanceAdapter(Activity activity, Class<MemberAttendance> modelClass, int modelLayout, Query ref) {
super(activity, modelClass, modelLayout, ref);
}
#Override
protected void populateView(View view, MemberAttendance memberAttendance, int i) {
String sport = memberAttendace.getAttended();
Date date = new Date(memberAttendance.getTimestamp());
// Create views and assign values
TextView dayTxtView = (TextView) view.findViewById(R.id.dayTxtView);
dayTxtView.setText(new SimpleDateFormat("dd-MM-yyyy").format(date););
TextView sportTxtView = (TextView) view.findViewById(R.id.sportTxtView);
sportTxtView.setText(sport);
//I think you want to show the time here, not the date
TextView dateTxtView = (TextView) view.findViewById(R.id.dateTxtView);
dateTxtView.setText(new SimpleDateFormat("HH:mm:ss").format(date));
}
}
Edit: As for your comment in querying the attendances by date, check the edits I made in the structure above and then use a Firebase Query like
ref.child("members")
.child(<memberIdHere>)
.child("attendance")
.orderByChild("date")
.equalTo(<yourDateHere>);
Instead of using HashMap I would recommended to create another object like AttendedSport as variable inside MemberAttendance then Firebase will map the data for with out using HashMap inside populateView you could get data like
memberAttendance.getAttendedSport().getSport() and memberAttendance.getAttendedSport().getTimeStamp()
I'm not guarantee it would fix your problem but I think it is less error prone.
Related
For months I have created a chat for the Android system using Firebase as a database.
I followed this guide here
( link ) and at the beginning it was all right, the chat was good and it didn't have any kind of delays. I then started to add other particularities, such as the display or not of the message and the status of the participants (online and offline) and from that moment three problems began to manifest in particular:
1) when I change the chat activity to go to another and then return to the chat, the layout appears empty without messages and if you try to change the activity the application closes itself. I found out that I get this error:
E/RecyclerView: No adapter attached; skipping layout
These are the files that make up the part related to chat:
MessageChat.java
public class MessageChat {
private String sender;
private String receiver;
private String msg;
private String currenttime;
private boolean isseen;
public MessageChat(String sender, String receiver, String msg, String currenttime, boolean isseen){
this.sender = sender;
this.receiver = receiver;
this.msg = msg;
this.currenttime = currenttime;
this.isseen = isseen;
}
public MessageChat(){}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getReceiver() {return receiver;}
public void setReceiver(String receiver) { this.receiver = receiver;}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getCurrenttime() {
return currenttime;
}
public void setCurrenttime(String currenttime) {
this.currenttime = currenttime;
}
public boolean isIsseen() {return isseen;}
public void setIsseen(boolean isseen) {this.isseen = isseen;}
}
msgAdapter.java
public class msgAdapter extends RecyclerView.Adapter<msgAdapter.MsgViewHolder> {
public static final int INT_TYPE_LEFT = 0;
public static final int INT_TYPE_RIGHT = 1;
private static List<MessageChat> mChat;
private static Context context;
private FirebaseUser fuser;
public msgAdapter(List<MessageChat> msg, Context context) {
this.mChat = msg;
this.context = context;
}
#Override
public msgAdapter.MsgViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == INT_TYPE_RIGHT) {
View view = LayoutInflater.from(context).inflate(R.layout.right_message, null);
msgAdapter.MsgViewHolder msgViewHolder = new msgAdapter.MsgViewHolder(view);
return msgViewHolder;
}else{
View view = LayoutInflater.from(context).inflate(R.layout.left_message, null);
msgAdapter.MsgViewHolder msgViewHolder = new msgAdapter.MsgViewHolder(view);
return msgViewHolder;
}
}
#Override
public void onBindViewHolder(final msgAdapter.MsgViewHolder holder, final int position) {
MessageChat msg = mChat.get(position);
holder.show_msg.setText(msg.getMsg());
if ((position == mChat.size()-1) && msg.getSender().equals(fuser.getUid())){
if (msg.isIsseen()){
holder.tv_seen.setText(" Seen ");
holder.tv_seen.setVisibility(View.VISIBLE);
}else {
holder.tv_seen.setText(" Sent ");
holder.tv_seen.setVisibility(View.VISIBLE);
}
}else{
holder.tv_seen.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
return mChat.size();
}
public static class MsgViewHolder extends RecyclerView.ViewHolder {
TextView username, show_msg, tv_seen;
public MsgViewHolder(final View itemView) {
super(itemView);
show_msg = (TextView) itemView.findViewById(R.id.show_msg);
tv_seen = (TextView) itemView.findViewById(R.id.tv_seen);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// item clicked
MessageChat msg = mChat.get(getAdapterPosition());
String ctime = msg.getCurrenttime();
TastyToast.makeText(context, ctime, TastyToast.LENGTH_LONG, TastyToast.INFO);
}
});
}
}
#Override
public int getItemViewType(int position) {
fuser = FirebaseAuth.getInstance().getCurrentUser();
if (mChat.get(position).getSender().equals(fuser.getUid())){
return INT_TYPE_RIGHT;
}else{
return INT_TYPE_LEFT;
}
}
}
On the internet I have found many answers that solve this problem in the following way, replacing this:
View view = LayoutInflater.from(context).inflate(R.layout.right_message, null);
to this:
View view = LayoutInflater.from(context).inflate(R.layout.right_message, parent, false);
But in my case I only got the busted chat with empty spaces between one comic and another.
Homefragment.java
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
private View v;
private ImageButton btn_send;
private EditText et_send_mex;
private DatabaseReference reference;
private msgAdapter mAdapter;
private List<MessageChat> mChat;
private RecyclerView recyclerView;
private FirebaseUser user;
private String Uid, Oid;
private static final String sId = "xyz1";
private static final String pId = "xyz2";
ValueEventListener seenListener;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel.class);
// Inflate the layout for this fragment
v = inflater.inflate(R.layout.fragment_home, container, false);
btn_send = v.findViewById(R.id.btn_send);
et_send_mex = v.findViewById(R.id.et_send_mex);
recyclerView = v.findViewById(R.id.rv_mex);
recyclerView.setHasFixedSize(true);
LinearLayoutManager llManager = new LinearLayoutManager(getContext());
llManager.setStackFromEnd(true);
recyclerView.setLayoutManager(llManager);
user = FirebaseAuth.getInstance().getCurrentUser();
Uid = user.getUid();
btn_send.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// notify = true;
String m = et_send_mex.getText().toString();
if (!m.equals("") || !m.equals("\n")){
if (Uid.equals(pId)){
sendMessage(Uid,sId,m);
}else if (Uid.equals(sId)){
sendMessage(Uid,pId,m);
}
}
}
});
readMessage();
return v;
}
private void seenMessage(final String senderId){
reference = FirebaseDatabase.getInstance().getReference("chats");
seenListener = reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()){
MessageChat msgchat = snapshot.getValue(MessageChat.class);
if (msgchat.getReceiver().equals(user.getUid()) && msgchat.getSender().equals(senderId)){
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("isseen", true);
snapshot.getRef().updateChildren(hashMap);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void sendMessage(String sender, String receiver, String message){
reference = FirebaseDatabase.getInstance().getReference();
HashMap<String, Object> hashMap = new HashMap<>();
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
month = month+1;
int day = c.get(Calendar.DAY_OF_MONTH);
int hour = c.get(Calendar.HOUR_OF_DAY);
int sec = c.get(Calendar.MINUTE);
String dt = day+" - "+month+" - "+year+", "+hour+":"+sec;
hashMap.put("currenttime", dt);
hashMap.put("sender", sender);
hashMap.put("receiver", receiver);
hashMap.put("msg", message);
hashMap.put("isseen", false);
reference.child("chats").push().setValue(hashMap);
et_send_mex.setText("");
}
private void readMessage (){
mChat = new ArrayList<>();
mAdapter = new msgAdapter(mChat,getContext());
recyclerView.setAdapter(mAdapter);
reference = FirebaseDatabase.getInstance().getReference("chats");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mChat.clear();
for (DataSnapshot snapshot: dataSnapshot.getChildren()){
MessageChat chat = snapshot.getValue(MessageChat.class);
mChat.add(chat);
if (!chat.getSender().equals(Uid)){
Oid = chat.getSender();
seenMessage(Oid);
}
}
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
// user status
private void status(String status){
user = FirebaseAuth.getInstance().getCurrentUser();
reference = FirebaseDatabase.getInstance().getReference("Users").child(user.getUid());
HashMap<String, Object> hashMap = new HashMap<>();
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
month = month+1;
int day = c.get(Calendar.DAY_OF_MONTH);
int hour = c.get(Calendar.HOUR_OF_DAY);
int sec = c.get(Calendar.MINUTE);
String dt = day+" - "+month+" - "+year+", "+hour+":"+sec;
hashMap.put("lastaccess", dt);
hashMap.put("status", status);
reference.updateChildren(hashMap);
}
#Override
public void onResume() {
super.onResume();
status("online");
recyclerView.setAdapter(mAdapter);
}
#Override
public void onPause() {
super.onPause();
reference.removeEventListener(seenListener);
status("offline");
}
}
I was also advised to add in here:
#Override
public void onResume() {
super.onResume();
status("online");
}
The following code:
recyclerView.setAdapter(mAdapter);
But with poor results (maybe you can suggest me if it is right to add this part here or not, thank you very much)
2) When I send a message, it often takes a long time to reach the database, let's say that Firebase is not really a realtime database. Here I have not encountered any type of error, it is simply very slow.
3) Later I also added the change of state, simply when the application is closed or in background ( onPause () ), the state is set to offline in the database, otherwise it is online. But often it doesn't work properly, probably application crashes or delays affect this.
I remain available for any other part of the code or for clarification.
I thank you in advance for your help and I apologize for my bad English, I have been working on this application since last spring and I still have not been able to solve these problems.
first thing you want to do is, remove the part in your onCreate.
reference = FirebaseDatabase.getInstance().getReference("chats");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
readMessage();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Here you basically put a reference on the database (chats) and every time it changes, it will call your function readMessage, which will always override your messages and put another listener on the same spot. Make sure you understand, that addValueEventListener is triggered every time the tree/path (chats) in firebase is updated!
You could simply replace the code from above with:
readMessage();
that would already make sure it is listening to your db. I believe that firebase is not slow, but that the two listeners maybe overriding their result.
About the next part i am not 100%, but i believe you can remove
mAdapter = new msgAdapter(mChat,getContext());
recyclerView.setAdapter(mAdapter);
from onDataChange (in readMessage) and put it directly under that part where you create the ArrayList. Like this:
mChat = new ArrayList<>();
mAdapter = new msgAdapter(mChat,getContext());
recyclerView.setAdapter(mAdapter);
reference = FirebaseDatabase.getInstance().getReference("chats");
I hope i understood your problem and my answer will give you a bit more clarity :)
Greetings!
This question already has answers here:
FirebaseListAdapter not pushing individual items for chat app - Firebase-Ui 3.1
(2 answers)
Closed 4 years ago.
I'm trying to implement a FirebaseRecyclerAdapter For the first time, but it just never gets called! I've checked the Firebase Guide Here but no good.
Have also checked similar threads that reported "Deleting Has FixedSize()" fixed it for them but that's not the case Here
Here's part of my database
and Here's my code for the adapter and model:
FirebaseRecyclerAdapter<Complaint, ComplaintHolder> TestAdapter;
DatabaseReference mRef;
FirebaseUser mUser;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUser = FirebaseAuth.getInstance().getCurrentUser();
mRef = FirebaseDatabase.getInstance().getReference("AccountsComplaintBasdNode").child(mUser.getUid());
Query query = mRef;
FirebaseRecyclerOptions<Complaint> mOptions = new FirebaseRecyclerOptions.Builder<Complaint>()
.setQuery(query, Complaint.class)
.build();
if (TestAdapter == null) {
TestAdapter = new FirebaseRecyclerAdapter<Complaint, ComplaintHolder>(mOptions) {
#NonNull
#Override
public ComplaintHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(getActivity()).inflate(R.layout.list_item, viewGroup, false);
Toast.makeText(getActivity(), "Please get called", Toast.LENGTH_SHORT).show();
return new ComplaintHolder(v);
}
#Override
protected void onBindViewHolder(#NonNull ComplaintHolder holder, int position, #NonNull Complaint model) {
holder.TitleTv.setText(model.getComplaintTitle());
SimpleDateFormat smf = new SimpleDateFormat("yyyy/MM/dd");
String dateString = smf.format(model.getDate());
holder.DateTv.setText(dateString);
}
///Model Object here
public Complaint() {
}
private String ComplaintTitle;
private String details;
private Date mDate;
private String PhotoUrl;
public Complaint(String complaintTitle, String details, Date date, String photoUrl) {
ComplaintTitle = complaintTitle;
this.details = details;
mDate = date;
PhotoUrl = photoUrl;
}
public void setComplaintTitle(String complaintTitle) {
ComplaintTitle = complaintTitle;
}
public void setDetails(String details) {
this.details = details;
}
public void setDate(Date date) {
this.mDate = date;
}
public void setPhotoUrl(String photoUrl) {
PhotoUrl = photoUrl;
}
public String getComplaintTitle() {
return ComplaintTitle;
}
public String getDetails() {
return details;
}
public Date getDate() {
return mDate;
}
public String getPhotoUrl() {
return PhotoUrl;
}
The FirebaseRecyclerAdapter uses an event listener to monitor changes to the Firebase query. To begin listening for data, call the startListening() method. Make sure you have finished any authentication necessary to read the data before calling startListening() or your query will fail.
So seems only you need is to call TestAdapter.startListening(); in onStart() method and don't forget to call TestAdapter.stopListening(); in onStop() as well but before calling stopListening() always check agains null
like:if(TestAdapter != null)
For more information and example: https://github.com/firebase/FirebaseUI-Android/blob/master/database/README.md
I want to set RecyclerView with Child of Current User Id by using getCurrentUser().getUid().The data structure you can see in image below,
In image above, SQyOq80egYehjqx4sgiyeNcW8P02 is current userId and I want to get all child of those id and show in RecyclerView. In above image, the child is wed5qPTCdcQVzVlRcBrMo1NX43v1 and their value is Sep 29, 2018. My question is how to get those childern values separately and show in RecyclerView. As an example, I wrote code for Date (the value of current userId), which gives fatal error. I know error in Model class which I am unable to understand.
Note: this line gives error. Log.d("sdfsdfdgfdfsdfd", blogPost.getDate());
Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("Friends").child(uid);
FirebaseRecyclerOptions<BlogPost> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<BlogPost>()
.setQuery(query, BlogPost.class)
.build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<BlogPost, BlogPostHolder>(firebaseRecyclerOptions) {
#Override
protected void onBindViewHolder(#NonNull BlogPostHolder blogPostHolder, int position, #NonNull BlogPost blogPost) {
Log.d("sdfsdfdgfdfsdfd", blogPost.getDate());
blogPostHolder.setBlogPost(blogPost);
}
#Override
public BlogPostHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new BlogPostHolder(view);
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
#Override
protected void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
if (firebaseRecyclerAdapter!= null) {
firebaseRecyclerAdapter.stopListening();
}
}
private class BlogPostHolder extends RecyclerView.ViewHolder {
private TextView userDateTextView;
BlogPostHolder(View itemView) {
super(itemView);
userDateTextView = itemView.findViewById(R.id.user_date);
}
void setBlogPost(BlogPost blogPost) {
String date = blogPost.getDate();
userDateTextView.setText(date);
}
}
}
Model:
public class BlogPost {
public String date;
public BlogPost() {}
public BlogPost(String date) {
this.date = date;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
change child key in firebase to be date
The wed5qPTCdcQVzVlRcBrMo1NX43v1 in your JSON seems to be dynamic, meaning that each user has a different key. The Firebase client has no way to parse that information into your BlogPost class, which only has static properties.
This means you'll have to provide your own SnapshotParser class to convert the DataSnapshot into the BlogPost object. Based on the FirebaseUI documentation that should look something like this:
FirebaseRecyclerOptions<BlogPost> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<BlogPost>()
.setQuery(query, , new SnapshotParser<Chat>() {
#NonNull
#Override
public BlogPost parseSnapshot(#NonNull DataSnapshot snapshot) {
// first let Firebase read any static properties
BlogPost post = snapshot.getValue(BlogPost.class);
// then do the parsing of the dynamic properties ourselves
for (DataSnapshot friendSnapshot: snapshot.getChildren()) {
String friendUID = friendSnapshot.getKey();
String friendDate = friendSnapshot.getValue(String.class);
post.setDate(friendDate);
}
return post;
}
}).build();
The above code is invoked by FirebaseUI for each new snapshot it gets from the database. It first calls snapshot.getValue(BlogPost.class) to convert the static parts of the JSON into a post, and then parses the friends itself. For now it sets any value it finds to the date property of the post. You may need to modify that to fit your exact use-case.
i have a FirebaseListAdapter which retrieves all the uid from the user but i want it to retrieve the names instead.
i have two child. one is to store all the uid of the connected users for a chat, and the other contains their information such as names. how do i convert the retrieved values (uid) into names and display it as shown below.
i have attached a snippet of how my app looks like currently and i want it to show names instead of uid.
FirebaseListAdapter<String> firebaseListAdapter = new FirebaseListAdapter<String>(getActivity(), String.class, R.layout.fragment_chatfprow, mDatabase) {
#Override
protected void populateView(View v, String model, int position) {
TextView text = v.findViewById(R.id.text1);
text.setText(model);
}
};
i think there is something to do with these lines of code but i cant figure out how.
This is how my Firebase ListView looks like
You need a model class for Firebase UI Database with an empty constructor for example:
public class Users {
private String mName;
private String mMessage;
public Users() {} // Required for Firebase
public Users(String name, String message) {
mName = name;
mMessage = message;
}
public String getName() { return mName; }
public void setName(String name) { mName = name; }
public String getMessage() { return mMessage; }
public void setMessage(String message) { mMessage = message; }
}
Then in Adapter creation you can do like this:
FirebaseListAdapter<Users> firebaseListAdapter = new FirebaseListAdapter<Users>(getActivity(), Users.class, R.layout.fragment_chatfprow, mDatabase) {
#Override
protected void populateView(View v, String model, int position) {
TextView text = v.findViewById(R.id.text1);
text.setText(model.getName());
}
};
You can take a look here from more informations: https://github.com/firebase/FirebaseUI-Android/blob/master/database/README.md
I have this DB structure:
{
"customers" : {
"-L-OcgJ0kwTNSm6HoSvG" : {
"address" : "Test Alamat",
"birthday" : "1990-12-03",
"email" : "Dodi#gmail.com",
"name" : "Dodi",
"outletID" : "2673",
"phone" : "09888777111"
}
}
}
Now i want to load all data of "customers" into ListView using FirebaseUI-Android library. And here is the codes:
Query query = FirebaseDatabase.getInstance().getReference().child("customers").limitToLast(50);
FirebaseListOptions<Customers> options = new FirebaseListOptions.Builder<Customers>()
.setLayout(R.layout.row_customer)
.setQuery(query, Customers.class)
.build();
FirebaseListAdapter<Customers> adapter = new FirebaseListAdapter<Customers>(options) {
#Override
protected void populateView(View view, Customers customer, int position) {
((TextView) view.findViewById(R.id.txtCustomerName)).setText(customer.name);
((TextView) view.findViewById(R.id.txtCustomerAddress)).setText(customer.address);
((TextView) view.findViewById(R.id.txtCustomerPhone)).setText(customer.phone);
//and i've set the adapter into ListView
((ListView)layout.findViewById(R.id.lvCustomerList)).setAdapter(adapter);
And here is Customers.java:
#IgnoreExtraProperties
public class Customers {
public String name, outletID, address, phone, birthday, email;
public Customers() {
}
public Customers(String name, String outletID, String address, String phone, String birthday, String email) {
this.name = name;
this.outletID = outletID;
this.address = address;
this.phone = phone;
this.birthday = birthday;
this.email = email;
}
}
Please help me what is the problem with my source code?
i've run it and the data failed to display (only blank on my listview). There's no errors on my Android Studio logs.
I recommend to you to create custom Adapter and to use a RecyclerView (it is faster and better than a ListView )
Something like this:
public class CustomerAdapter extends RecyclerView.Adapter<CustomerAdapter.MessageViewHolder> {
private List<Customer> customerList;
private Context context;
public CustomerAdapter(List<Customer> customerList, Context context) {
this.customerList= customerList;
this.context = context;
}
#Override
public CustomerAdapter.MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.your_layout, parent, false);
return new CustomerAdapter.MessageViewHolder(v);
}
public class CustomerViewHolder extends RecyclerView.ViewHolder {
public TextView customername, customeraddress, customerphone;
public CustomerViewHolder(View view) {
super(view);
customername = view.findViewById(R.id.txtCustomerName);
customeraddress = view.findViewById(R.id.txtCustomerAddress);
customerphone = view.findViewById(R.id.txtCustomerPhone);
}
}
#Override
public int getItemCount() {
return customerList.size();
}
#Override
public void onBindViewHolder(final CustomerAdapter.MessageViewHolder holder, final int position) {
holder.customername.setText(customerList.get(position).getName;
holder.customeraddress.setText(customerList.get(position).getAddress;
holder.customerphone.setText(customerList.get(position).getPhone;
}
And you can get the data like this:
FirebaseDatabase.getInstance().getReference().child("customers").addValueEventListener(new ValueEventlistener{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<Customer> custoemrList = new ArrayList<>();
for (final DataSnapshot snapshot : dataSnapshot.getChildren()) {
Customer customer = new Customer();
customer.setName(snapshot.child("name").getValue().toString();
...
...
customerList.add(customer);
}
customerAdapter= new customerAdapter(customerList, YourActivity.this);
recyclerView.setAdapter(chatsAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
});
And in your Customer class you have to add getters and setters.
Press Alt + Insert -> Getters and Setters -> Select All -> Enter
This should be it
Change this line of code:
Query query = FirebaseDatabase.getInstance().getReference().child("customers").limitToLast(50)
with
Query query = FirebaseDatabase.getInstance().getReference()
.child("customers")
.orderByChild("name")
.limitToLast(50);