In my firebase database the date is the key value (node) which has its own children. How to retrieve the date into firebase adapter and show it in the listview? I am using the below code but the list is blank.
databaseReference = FirebaseDatabase.getInstance().getReference().child("Lectures").child(post_key);
FirebaseListOptions<String> options = new FirebaseListOptions.Builder<String>()
.setLayout(R.layout.subject_list_heading)
.setQuery(databaseReference, String.class)
.build();
adapter = new FirebaseListAdapter<String>(options) {
#Override
protected void populateView(View v, String model, int position) {
TextView subject_name = v.findViewById(R.id.tv_sub_heading);
subject_name.setText(model);
}
};
list_of_date.setAdapter(adapter);
This is the JSON object:
{
"-LHSdSCzD_tZhzqvSOw_" : {
"17-7-2018" : {
"Absent" : "0",
"Present" : "1",
"Total_Lectures" : "1"
}
I want to retrieve the date in the listview.
Any help is appreciated.
To solve this, please add the following lines of code in the onStart() and onStop() methods.
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
if(adapter != null) {
adapter.stopListening();
}
}
So because you are using a listener, you need to start listen for changes. If you are interested, this is a recommended way in which you can retrieve data from a Firebase Realtime database and display it in a RecyclerView using FirebaseRecyclerAdapter.
Related
For example, I'd like to display all orders that has fs_ID equal to FS02. I provided a screenshot of my firebase below:
This is my current code:
public class NewOrders extends AppCompatActivity {
public RecyclerView recyclerView;
public RecyclerView.LayoutManager layoutManager;
FirebaseDatabase database;
DatabaseReference requests;
FirebaseRecyclerAdapter<Request, OrderViewHolder> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_orders);
//Firebase
database = FirebaseDatabase.getInstance();
requests = database.getReference("Order_Header");
recyclerView = findViewById(R.id.listOrders);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
adapter = new FirebaseRecyclerAdapter<Request, OrderViewHolder>(
Request.class,
R.layout.order_layout,
OrderViewHolder.class,
requests.orderByChild("fs_ID")
.equalTo("FS02")
) {
#Override
protected void populateViewHolder(OrderViewHolder viewHolder, Request model, int position) {
viewHolder.txtOrderID.setText(adapter.getRef(position).getKey());
viewHolder.txtOrderStatus.setText(convertCodeToStatus(model.getStatus()));
viewHolder.txtOrderUsername.setText(model.getUsername());
viewHolder.txtOrderFname.setText(model.getFirstName());
viewHolder.txtOrderLname.setText(model.getLastName());
viewHolder.txtOrderEmail.setText(model.getEmail());
viewHolder.txtOrderAddress.setText(model.getAddress());
}
};
recyclerView.setAdapter(adapter);
}
private String convertCodeToStatus(String status){
//pasok db how
if (status.equals("OS1")) {
return "Placed";
}
else if (status.equals("OS2")) {
return "In progress";
}
else {
return "OS3";
}
}
}
The screen where it is suppose to show is empty, what might be the problem? Thanks
You seem to not be calling startListening anywhere, which is required for FirebaseUI to start observing the database. Right now you told the adapter what data to observe, and what to do with it, but you never told it to start doing so.
You'll typically want to start listening in the onStart of your activity, and then stop listening in onStop().
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
Also see the FirebaseUI documentation on the adapter lifecycle.
I'm working on Activity to show all the others app users except my user and i'm using Java android with Firebase .
But i cant find anyway to exclude item from DatabaseReference or from FirebaseRecyclerAdapter .
My Activity look like this
My Database look like this :
My code inside this Activity looks like below :
#Override
public void onStart() {
super.onStart();
database = FirebaseDatabase.getInstance();
myRef = database.getReference().child("users");
FirebaseRecyclerAdapter<Users,RecyclerViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Users, RecyclerViewHolder>(Users.class , R.layout.users_single_layout ,RecyclerViewHolder.class,myRef ) {
#Override
protected void populateViewHolder(RecyclerViewHolder viewHolder, Users model, int position) {
viewHolder.setDisolayName(model.getDisplay_name());
viewHolder.setStatus(model.getStatus());
viewHolder.setImage(model.getImager_thumb(), getContext());
frinds_relative.setVisibility(View.INVISIBLE);
final String users_id = getRef(position).getKey();
viewHolder.mview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent target = new Intent(getActivity() , user_profile.class);
target.putExtra("profile_id" , users_id) ;
startActivity(target);
}
});
}
};
users_recycler.setAdapter(firebaseRecyclerAdapter);
}
I will be thankful if you have the solution .
I faced something similar once and how i did it was..
First thing is to give the parent layout and id in the users_single_layout xml file;
Reference the parent layout in the viewholder;
Then hide all the content of file by :
android:visibility="gone"
When That is done, You set and if statement in your FirebaseRecyclerAdapter:
Check the Code Below:
users_recycler = new FirebaseRecyclerAdapter<Users,RecyclerViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Users, RecyclerViewHolder>(Users.class , R.layout.users_single_layout ,RecyclerViewHolder.class,myRef ) {
#Override
protected void populateViewHolder(RecyclerViewHolder viewHolder, Users model, int position) {
if (adapter.getRef(position).getKey.equals(currentUid){
viewholder.thelayout.setVisibility(View.GONE);
} else {
viewHolder.setDisolayName(model.getDisplay_name());
viewHolder.setStatus(model.getStatus());
viewHolder.setImage(model.getImager_thumb(), getContext());
frinds_relative.setVisibility(View.INVISIBLE);
final String users_id = getRef(position).getKey();
viewHolder.mview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent target = new Intent(getActivity() , user_profile.class);
target.putExtra("profile_id" , users_id) ;
startActivity(target);
}
});
}
}
};
users_recycler.setAdapter(firebaseRecyclerAdapter);
The FirebaseUI FirebaseRecyclerAdapter is a direct representation of the data in the underlying Query or exists at a location in a Firebase database. To exclude an item from an adapter, you have to exclude it first from the Firebase location or ensure it doesn't match that particular query anymore.
To achieve this, you can use the following line of code:
yourAdapter.getRef(position).removeValue();
I have a textView in my activity - say, "Username". It is supposed to be populated from a Firebase database. I am making the Firebase query in Asynctask so as not to block the activity. However that means that the TextView loads first, before the Firebase query is completely executed.
So what is the best way to refresh this textBox after the Firebase query is executed inside the AsyncTask and the username gets known?
I do not want to showprogressBar and block the activity while the data is being fetched from the database. That would defeat the purpose of doing it in AsyncTask.
Code for the AsyncTask is below
private class CheckUserLoginAndRetrieveDataFromFirebase extends AsyncTask <Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
if (thisAppUser!=null) {
setUserDataForToday();
if (createNewNode) { //This is the first time the User is logging in
createUsersNodesForFirstTime();
}
}
return null;
}
Code for my Firebase Query in the AsyncTask is below
public static void setUserDataForToday() {
setProperDatabaseReference(); //This sets reference to user specific nodes in the database
myRef.child("dashboard").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Dashboard dashboard = dataSnapshot.getValue(Dashboard.class);
if (dataSnapshot.getChildrenCount() > 0) {
createNewNode = false;
if (dashboard.checkIfTodaysDateExistsInDatabase()) {
//An entry for todays date exists in database, so no data change needed
myDashboard = dashboard;
}
I hope this example will help you
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUserDataForToday();
Log.d("MainActivity", "Process is not blocked");
}
public void setUserDataForToday() {
Log.d("MainActivity", "Called method");
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
database.child("users").child("1").child("name").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String userName = dataSnapshot.getValue(String.class);
Log.d("MainActivity", "Received value: " + dataSnapshot.getValue());
dataSnapshot.getKey();
TextView textView = (TextView) findViewById(R.id.textUserName);
textView.setText(userName);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("MainActivity", "DB error: " + databaseError.getMessage());
}
});
}
public void onClick(View v) {
setUserDataForToday();
}
}
If you are working with Android studio click tools>Firebase>Realtime Database and follow instructions. This will get you started. You probably want to click tools>firebase>authentication if you want to have users and if you want only certain users to access certain things configure rules for the database. Frank is correct no need for async task.
I have used Firebase RecyclerViewAdapter extensively in my app but since the below code doesn't fire populateViewHolder without any data to load in the first place, I can't show the load complete message for the initial load
RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, android.R.layout.two_line_list_item, ChatHolder.class, mRef) {
#Override
public void populateViewHolder(ChatHolder chatMessageViewHolder, Chat chatMessage, int position) {
chatMessageViewHolder.setName(chatMessage.getName());
chatMessageViewHolder.setText(chatMessage.getText());
}
};
recycler.setAdapter(mAdapter);
What you're describing is covered by this feature: Handle empty state for recycleview. You can handle this by implementing onDataChanged() in your adapter. A snippet from the sample app of FirebaseUI:
#Override
protected void onDataChanged() {
// if there are no chat messages, show a view that invites the user to add a message
mEmptyListView.setVisibility(
mRecyclerViewAdapter.getItemCount() == 0 ? View.VISIBLE : View.INVISIBLE
);
}
if(chatMessage.getName().equals("")){ //null value }else{
//execute code }
Override onDataChanged() and check in it
mAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, android.R.layout.two_line_list_item, ChatHolder.class, mRef) {
#Override
public void populateViewHolder(ChatHolder chatMessageViewHolder, Chat chatMessage, int position) {
chatMessageViewHolder.setName(chatMessage.getName());
chatMessageViewHolder.setText(chatMessage.getText());
}
#Override
protected void onDataChanged() {
// do your tests here
}
};
I am using FirebaseRecyclerAdapter that comes with FirebaseAndroid-UI library and I assume that when the data will change on Firebase it will automatically refresh and update the RecyclerView.
My code is simple:
Firebase firebasePicturesRef = new Firebase(FIREBASE_URL);
mAdapter = new FirebaseRecyclerAdapter<Image, ImageViewHolder>(
Image.class, R.layout.pictures_grid_item,
ImageViewHolder.class, firebasePicturesRef) {
#Override
protected void populateViewHolder(ImageViewHolder viewHolder, Image model, int position) {
super.populateViewHolder(viewHolder, model, position);
Glide.with(getActivity()).load(model.getThumbnailUrl()).into(viewHolder.mImageView);
}
};
I have also tried to manually refresh the adapter using notifyDatasetChanged in the the onDataChange method:
firebasePicturesRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (mAdapter != null)
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Am I doing something wrong? What is the fix?
I found the problem, i was calling mAdapter.cleanup(); in onStop() of the fragment. Removing it fixed the problem.
Instead of doing cleanup in onStop(); it should be called in onDestroy()
As suggested by Frank:
In general you should call cleanup() in the "opposite" method from where you create the adapter. So onCreate()<->onDestroy(), onStart()<->onStop(), onPause()<->onResume()