here is my function to get data :
public void retrievedata(){
FirstRef.child(obj.getsEventID()).orderByChild("date").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s)
{
if (dataSnapshot.exists())
{
DisplayMessages(dataSnapshot);
}
}
#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) {
}
});
}
private void DisplayMessages(DataSnapshot dataSnapshot) {
Iterator iterator = dataSnapshot.getChildren().iterator();
String Article = (String) ((DataSnapshot) iterator.next()).getValue();
String Key = (String) ((DataSnapshot) iterator.next()).getValue();
String Organisateur = (String) dataSnapshot.child("name").getValue().toString();
String date = (String) dataSnapshot.child("date").getValue().toString();
Date resultdate = new Date(Long.parseLong(date));
String date2 = DateFormat.format(resultdate).toString();
ListOfArticles.add(0,new ListItemTypeOne(Key, Article, Organisateur, date2));
adapter.notifyDataSetChanged();
}
Let's suppose I have 10 articles, they are kept in the disk memory thanks to :
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Now, while I was offline someone added 2 more articles which makes 12.
If I go online, and execute the function "retrieve data", will it simply call the onchildadded with the 10 child in the memory and the 2 new child from the firebase database or will it download all of the 12 childs from firebase ?
When you attach a listener for data that is already present on the device, Firebase immediately satisfies the listener with the data that it has on the device.
So the Firebase client will immediately call your onChildAdded with the 10 child nodes that we persisted earlier.
It then sends a request to the server to get the most up to date version. It does this with a so-called delta-sync, meaning that it by sending a hash value of the local state, which the server compares to the current state in the database. The server then sends the delta back, which the Firebase client then uses to update its internal snapshot and the state on disk.
If there are any changes, the Firebase client then fires the correct local events to allow your application to update to the new state. So in the case where two child nodes were added, it will call onChildAdded for each of those.
If you were to use a listener with a limit, say limitToLast(10), then the Firebase client would also call onChildRemoved for the two children that are no longer within that query (since they were pushed out by the new children).
The previously cached 10 children will be loaded from disk and not transferred from the server again.
Related
On application start the ChildEventListener is getting fired the amount of child present in the firebase database. For instance, if I have already 3 children present in the database, the listener will get invoke 3 times when I start my application. s I have defined the code for the listener in my service class and I am starting the service from my Splash class.
From SplashScreen.class
startService(new Intent(this , BackgroundService.class));
From BackgroundService.class
listenToJob() method, is in onStartCommand() method of Service
private void listenToJob (){
String collectionName = "rideRequest";
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference(collectionName);
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
Toast.makeText(BackgroundService.this, "Hey, new child is added.", Toast.LENGTH_SHORT).show();
OnChildCreated(snapshot);
}
#Override
public void onChildChanged(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot snapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
};
myRef.addChildEventListener(childEventListener);
}
I don't what cause this behavior. Isn't onChildAdded() method should only be invoked when a new child is added to the database? I have 3 children already present in the database and when I open my app this onChildAdded() method is getting invoke 3 times.
I want this method to fire up only when child is added to the database!
According to the Firebase documentation on listening for child events, the onChildAdded:
is triggered once for each existing child and then again every time a new child is added to the specified path.
So what you're seeing is the expected behavior.
If you want to only be informed of new children, you need to have something that defines when a child is "new". For example, if you're using Firebase's built-in push() method to generate the child nodes, you can use the keys that generates to only get child nodes that are generated after you start listening with:
String key = myRef.push().getKey()
myRef.orderByKey().startAt(key).addChildEventListener(childEventListener);
i am trying to get reference or snapshot of newly added child on firebase
i have solve it by different way
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
}
myRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s)
{
}
My question is that both are return a complete snapshot means all this nodes in firebase is there any way getting child which newly added ("this will improve speed")
When you attach a listener to a location or a query, the listener will initially fire with all data that exists at that location or that matches the query. The database has no concept of "new" data, although your application may have that concept.
There are a few options to reduce the data that is retrieved, or the data that is passed to your listener:
If you're using disk persistence, the application may have a previous snapshot of the data in its disk cache. In that case, only the delta between the previous snapshot and the current snapshot is retrieved from the server. But the entire current snapshot is passed to your listener, so that you can render the UI correctly for the while current data.
If you only want to process the data since a certain moment, you'll need to only request that data from the database. You can typically do this by storing the key of the data you last processed in your local state, and then using a query like this to only get the new update:
myRef.orderByKey().startAt("mostRecentKeyWeHaveAlreadyProcessed").add...Listener
How can i implement a listener on firebase to keep check if data has changed in firebase? for example, a user insert a data in firebase, a second user is checking a listview of that data, i want to refresh that listview automatically.
You need to listen to Firebase Database changes, and once data added to the database, you will be notified on client side and you will receive the data that is added to firebase database because it's realtime database.
mFirebaseDatabase.child("yourNode").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
// here you need to handle the value added.
}
#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) {
}
});
There are two ways.
Way 1: If possible, create a callback and after user insert a new item, you callback will fire.
Way 2: Every N second (2-5), you could make a request to server to ask him if new data avaliable.
Also if you are building a list with recyclerView, for efficient updating list, use DiffUtil.
Which case is better, you decide. I don't work with firebase list.
As i am creating the chat app, for it i am using the Firebase.
It works perfectly, only one problem which i am getting that each time i am getting whole list of data from Firebase, when new item is added or deleted into it.
What i want that , only newly added record should come from Firebase , not whole list of data.
Please check my below code for it
ArrayList<ChatMessage> MY_ARRAYLIST= new ArrayList<>();
MsgViewHolder viewModel = ViewModelProviders.of(this).get(MsgViewHolder.class);
LiveData<DataSnapshot> liveData = viewModel.getDataSnapshotLiveData();
liveData.observe(this, dataSnapshot -> {
if (dataSnapshot != null) {
MY_ARRAYLIST.clear(); // I NEED TO CLEAR THE ARRAY-LIST TO GET THE REFRESHED DATA..I DO NOT WANT TO LOAD WHOLE LIST ON EACH TIME
if (dataSnapshot.exists())
for (DataSnapshot ds : dataSnapshot.getChildren()) {
ChatMessage bean = ds.getValue(ChatMessage.class);
assert bean != null;
MY_ARRAYLIST.add(bean);
}
}
});
As in above code i am using MY_ARRAYLIST.clear() to clear data, to get the newly added record.On each time from DataSnapshot , i am getting the whole list of data, whenever new record added or deleted.Is their any method to get only newly added data NOT whole List from Firebase?
You can use addChildEventListener() to you DatabaseReference which will notify you on different callback method when any child is add/removed/updated/deleted or moved
databaseRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
// If any child is added to the database reference
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
// If any child is updated/changed to the database reference
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
// If any child is removed to the database reference
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
// If any child is moved to the database reference
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("FirebaseListAdapter", "Listen was cancelled, no more updates will occur");
}
});
The DataSnapshot in each callback will provide you the information of the child
This is by design, in a real-time system there is no concept of the "latest" data because it's always changing. However, if you want to only display items added to the list after the page has loaded, you can do the following:
var newItems = false;
var eventsList = new Firebase('https://*****-messages.firebaseio.com/');
eventsList.on('child_added', function(message) {
if (!newItems) return;
var message = message.val();
$.notification(message.message);
});
eventsList.once('value', function(messages) {
newItems = true;
});
above answer original by (anant)
(my) another solution
if you have control over your database schema you can add a 'datetime' element in your object and store the value of the time just before adding it to database in Epoch format, then you can simply get the list of objects in newly added order with limit like this.
ds.orderBy("datetimeSent", Direction.DESCENDING).limit(10);
I think you can use this listener onChildAdded() I provided a link to the documentation.
Listen for child events
You can try Query for query on database,add on child as date and time and query based on that data filed after every result update the query to last sync date and time
addValueEventListener gives all the data whenever something changed in the database, due to this I have implemented addChildEventListener to get the only new item when there is a something new in the database.
Currently, the problem I am facing is whenever I open app, addChildEventListener fetch all the item one by one in onChildAdded method.
Is there any way that I can fetch only new items in Firebase Realtime Database? Here is my code:
mDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
News news = dataSnapshot.getValue(News.class);
Log.i("YES-onChildAdded", news.getId()+"/"+news.getHeadline());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
News news = dataSnapshot.getValue(News.class);
Log.i("YES-onChildChanged", news.getId()+"/"+news.getHeadline());
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
News news = dataSnapshot.getValue(News.class);
Log.i("YES-onChildRemoved", news.getId()+"/"+news.getHeadline());
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
News news = dataSnapshot.getValue(News.class);
Log.i("YES-onChildMoved", news.getId()+"/"+news.getHeadline());
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.i("YES-Cancelled", databaseError.getMessage());
}
});
When you attach a listener on a particular DatabaseReference it means that the listener will retrieve all data from that location where the reference points to. Because Firebase database doesn't store metadata you need to add a TIMESTAMP for each record yourself. Defining a certain data then you can create a query to filter your database accordingly. Unfortunately, this is a behaviour that cannot be changed in Fireabse.
Assuming you have a node named item and each item within this node has a TIMESTAMP correctly set, the code to query a database using a TIMESTAMP should look like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("item").orderByChild("timestamp");
Further more you can query your database using limitations like this:
Query query = rootRef.child("item")
.orderByChild("timestamp")
.startAt(startingTime)
.endAt(endingTime);