I have successfully been able to save data in RTD of Firebase using
databaseIngredients.child(StringId).setValue(ingredients);
Where the "ingredients" is a String taken from EditText and StringId is a unique ID by the "push" method. I have referred to many tutorials but I am not able to read it, I want to update my RecyclerView every time my database is updated with new data. I just want to display all data in my Database using recyclerView. The ValueEventListener method is not understood by me. Please be patient as I understand the reply, new to Firebase.
Reading data is very simple, all you need to do is set a listener that listens for change in value in the database reference you provided.
There are two listeners for that purpose,
One Time Listener(addListenerForSingleValueEvent), which only reads data once you make request. For this,
DatabaseReference reference = database.getReference("Database").child(StringId).setValue(ingredients);
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapShot.exists()){
//update recyclerview or do anything with your data
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Continuous Data Listener(addValueEventListener), which is used to get data every time it changes in server
DatabaseReference reference = database.getReference("Database").child(StringId).setValue(ingredients);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapShot.exists()){
//update recyclerview or do anything with your data
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
You can use FirebaseRecyclerAdapter . You'll need a model class and a ViewHolder class.
If you're using new version of firebase-ui then you have to use FirebaseRecyclerOptions along with FirebaseRecyclerAdapter
Here's the official documentation
Related
This my Firebase database:
This is my code for retrieving data in to list view, I want to get all data from Tehsil_hin and Tid with specific id in two different arraylist.
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("Tehsil");
Query query = myRef.orderByChild("DID").equalTo(did);
query.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot postSnapshot: snapshot.getChildren())
{
areas.add(snapshot.child("Tehsil_Hin").getValue(String.class));
areasid.add(snapshot.child("TID").getValue(int.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//System.out.println("The read failed: " + firebaseError.getMessage());
}
});
I'm not reciving data from that
You're never notifying an adapter that data was updated, so no listview will get updated
You need to notify an adapter outside the loop, assuming the loop is in fact entered (please add log statements to debug further)
You should also keep the error method body uncomment because that also is an area where you're not seeing anything happening
If you want to access the data from those children nodes, instead of using query you can just use DatabaseReference and using orderByChild() and equalTo() can access the data which only has the value you want.
In code it looks something like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference().child("Tehsil");
// specificTID is the value which you want to compare to the value stored in database
rootRef.orderByChild("TID").equalTo(specificTID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot data: dataSnapshot.getChildren()){
// use array1.add to store value in your arrayList
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Now you have to update the value to the ArrayAdapter and set it up to your listView to be able to display the data.
ArrayAdapter adapter = new ArrayAdapter(Main2Activity.this, android.R.layout.simple_list_item_1, array);
listView.setAdapter(adapter);
You can do this with both of your children and store the values in different arrays. You can also use different listViews to display the data.
I'm a beginner user of android studio.I need your help in this issue.
I wrote a code to save strings in firebase database, and I want to write a code that retrieve all the values under a certain key from multiple nodes and display it in a listview.
How can I do so ?
data structure:
DataBase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<String> a = new ArrayList<>();
a.add(dataSnapshot.child("imageURL").getValue().toString());
a.add(dataSnapshot.child("n1").getValue().toString());
a.add(dataSnapshot.child("n2").getValue().toString());
a.add(dataSnapshot.child("n3").getValue().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
and after that set this list to adapter using setAdapter ..
I hope this code will help you :)
I am storing user details 'firstname' and 'lastname' in UserNode. But when i want to retrieve that details then no data is being retrieved. I tried almost all solutions on the internet but nothing solved my problem. Here is my code for retrieving data of the current user:
FirebaseUser userr = FirebaseAuth.getInstance().getCurrentUser();
if (userr != null) {
String name = userr.getDisplayName();
Log.e("value", name);
}
but it says "println needs a message"
I also tried with this but nothing happened:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String acctname = (String)dataSnapshot.child("firstname").getValue();
Log.e("name", acctname);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
]1
Please help me I am stuck with it
You're reading a collection of user with a ValueEventListener. As the [Firebase documentation for reading lists with a value event](Listen for value events) explains:
While using a ChildEventListener is the recommended way to read lists of data, there are situations where attaching a ValueEventListener to a list reference is useful.
Attaching a ValueEventListener to a list of data will return the entire list of data as a single DataSnapshot, which you can then loop over to access individual children.
Even when there is only a single [child node], the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result.
So in your code:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String acctname = (String)childSnapshot.child("firstname").getValue();
Log.i("name", acctname);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
Using FirebaseUser:
FirebaseUser implements UserInfo and in UserInfo's getDisplayName() documentation says
Returns the user's display name, if available.
So, it is possible that FirebaseUser.getDisplayName() return null when display name is not set. In that case Log.e() receives null as message and therefore prints println needs a message
Using your own structure:
Instead of using type conversion use getValue(Class<T>) like so:
String acctname = dataSnapshot.child("firstname").getValue(String.class);
Please, read how to retrieve data from firebase. I think you have a problem because you don't have Class Model.
Your steps:
Create model UserModel with firstname and lastname field
Use listener (example from docs):
// Attach a listener to read the data at our posts reference
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Post post = dataSnapshot.getValue(Post.class);
System.out.println(post);
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
See other answers: How to retrieve data from one single userID Firebase Android and retrieving data from firebase android
I'm trying to display the "loc" of a part if its part number I given.
Here is what the data structure looks like:
{
"parts":{
"14521845": { "name":"TOOL EC160B/EC180B/EC210B/EC240", "loc":"EXC1", "sloc":"B3EGU01C03"},
"12829050": { "name":"SWITCH; IGNITION SWITCH", "loc":"PS01", "sloc":"85-06-013"},
"12829050": { "name":"SWITCH; IGNITION SWITCH", "loc":"COM1", "sloc":"B3RGK03D06"},
"20044893": { "name":"PARTS CATALOG_ENG_SPA_FRE_GER_KOR_EC210D", "loc":"EXC1", "sloc":"B3EGT01B02"}
}
}
Activity Code:
FirebaseDatabase firebaseDatabase=FirebaseDatabase.getInstance();
DatabaseReference databaseReference =firebaseDatabase.getReference("parts/"+curP);
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Products data=dataSnapshot.getValue(Products.class);
Log.i("",String.valueOf(data.getLoc()));
}
getLoc is the getter function for the Product class, and it returns the corresponding "loc" for the given curP. curP denoted the child values in parts.
The logic seems right to me, but I am not getting an output. Where am I going wrong here?
try this
getReference("parts").child(curP).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Products data = dataSnapshot.getValue(Products.class);
Log.i("", String.valueOf(data.getLoc()));
}
});
The problem is that what you are getting in onChildAdded() is not a whole Product object as you expect it to be.
In your database reference you are targeting a specific Product ("parts/"+curP) but using a ChildEventListener. The children of a specific product node are name, loc and sloc, so the onChildAdded() will trigger several times, giving you each of these properties as a dataSnapshot separately.
The two patterns you might use to get whole Product objects are either:
add a ChildEventListener directly to the "parts" node and you will get each of the Products as a child of that node, or;
if you are adding a listener directly to the node of a particular product, use a ValueEventListener, to get the whole of that nodes entry as one dataSnapshot.
You can try to use ValueEventListener. If you want read data once so use the addListenerForSingleValueEvent method, something like this:
private void getFirebaseLocValue(int curP) {
FirebaseDatabase firebase = FirebaseDatabase.getInstance();
DatabaseReference mDatabase = firebase.getReference("parts");
mDatabase.child(Integer.toString(curP))
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChildren()) {
Products data = dataSnapshot.getValue(Products.class);
Log.e("TAG", data.getLoc());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Or you can use addValueEventListener and will get data with any changes. I really don't think that ChildEventListener is a good idea to retrieve data from Firebase.
I have this scenario where in my app i am trying to query the child nodes and pass it on the list to recyclerview adapter and here comes the problem when i am scrolling up the recycler view items and if some one has inserted a post, my recyclerview is again coming to first post item and also i am using the viewpager with three fragments and whatever fragment i am on I am rolling back to the first fragment if some one has inserted the post how to solve this.
I have implemented this in following way mentioned below.
one way im thinking is i thought i would not listen to the childevent changes instead i would query the results and populate recyclerview later not listening to child events so that way everything states as it is and i dont know in firebase how do you retrieve values without implementing listeners I tried the singleValueEventListener that way still the behavior is same rolling back to first item or first fragment
guide me through solution how to get rid of this behavior.
Query query= databasePostsReference.orderByChild("timestamp");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<UserPostPOJO> listposts = new ArrayList<UserPostPOJO>();
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
Log.d(TAG, "onDataChange: entered list adding");
UserPostPOJO post =
snapshot.getValue(UserPostPOJO.class);
listposts.add(0,post);
}
if(listposts.isEmpty()){
empty.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
}
else
{
empty.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
makelist(listposts);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
private void makelist(List<UserPostPOJO> listposts) {
list = listposts;
Log.d(TAG,"size is "+ list.size()+"");
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new
LinearLayoutManager(getActivity()));
CustomRecyclerViewAdapter adapter = new
CustomRecyclerViewAdapter(getActivity(), list,"recentfragment");
recyclerView.setAdapter(adapter);
}
There is a method called removeEventListener() that you can call to remove a specific event listener. You get data out from your database and than call this method. So in order to make this work, please use the following code:
databaseReference.removeEventListener(valueEventListener);
In which databaseReference is the reference where you intially put the listener.
For more details please read the offcial doc.
Hope it helps.
Firebase has a FirebaseRecyclerAdapter which can be set to a RecyclerView. It takes a DatabaseReference or Query object and handles all the data synchronization between your database and your view.
For a database reference object, the same way one can add an event listener, it can also be removed, using removeEventListener.
Instead of creating an anonymous object like this
Query query= databasePostsReference.orderByChild("timestamp");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<UserPostPOJO> listposts = new ArrayList<UserPostPOJO>();
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
Log.d(TAG, "onDataChange: entered list adding");
UserPostPOJO post =
snapshot.getValue(UserPostPOJO.class);
listposts.add(0,post);
}
if(listposts.isEmpty()){
empty.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
}
else
{
empty.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
makelist(listposts);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
you can create a named object of ValueEventListener and remove it from the database reference object using removeEventListener, at the end of the onDataChange method
Query query= databasePostsReference.orderByChild("timestamp");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<UserPostPOJO> listposts = new ArrayList<UserPostPOJO>();
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
Log.d(TAG, "onDataChange: entered list adding");
UserPostPOJO post =
snapshot.getValue(UserPostPOJO.class);
listposts.add(0,post);
}
if(listposts.isEmpty()){
empty.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
}
else
{
empty.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
makelist(listposts);
}
query.removeEventListener(valueEventListener);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
query.addValueEventListener(valueEventListener);
The code inside onDataChange method gets executed only once as the ValueEventListener object is removed as soon as the last line of the method gets executed.