Going to parent of an entry in firebase database - android

I am attaching a picture of my firebase database. I am at OPL and I want to go to its parent. Is there somekind of "GetParent()" kind of fuction, like "GetChildren" that can take me there?

To read the data from database, you need to set listeners at appropriate locations. These listeners provide values for one time as well as for updates with the methods onChildAdded() and onChildChanged().
For your case, you should attach a childListener on the ActionList by using the line
mDatabase.child('ActionList').addChildEventListener(listenerName);
Set up the onChildAdded() method of this listener which provides a snapshot. Traversing through the children from that snapshot using dataSnapshot.getChildren() and to get their values use this function child.getKey() method.

Related

Sorting recyclerview by recently accessed

I am doing a side project of making an app (with Java since I already know it). I have a recyclerview which loads some data via the room database library. The elements of the recyclerview are clickable.
My problem is I want the user to be able to sort the recyclerview so that the most recently accessed items go to the top.
My original idea was to assign the entities to have two variables - a String list_name which also serves as the id, and an Int order_of_access. Also, in my ViewModel I have a getAllLists method which returns a livedata list. I have an onChanged listener in the fragment activity which nicely updates the recyclerview when data is added/removed.
When the user adds a new list, it is assigned an order_of_access of the listsize (+1). But when the user deletes a group of lists, or clicks on a list, I want to update the order_of_access, say with an updateOrderAccess method.
Do you think this is the best way of doing what I want?
Where should I place updateOrderAccess and how would you recommend it be written? Since the method getAllLists returns livedata, it is tempting to put updateOrderAccess in an observer in the fragment (in onChanged) - but this will obviously create an infinite loop. It seems more in the correct philosophy to put it in the ViewModel, but then how would you suggest the updateOrderAccess method to be written? I'm having some trouble conceptualising what I need.
I hope the question is not too vague - I will update it if you need more details.
Where should I place updateOrderAccess and how would you recommend it
be written?
I am so sure that you must write it in the view model, as long as updateOrderAccess() is editing the list which is observable then you have andexpose by that the ui state then you have to put it in view model, and the observers will be notified ( in this case it is recycle view) and it will redraw the list in the order you offered.
note: do not you ever update the state(ui data) outside the state holder so you implement UDF (unidirectional Data Flow) pattern.
see the references below to read more about UDF so you never get confused where to declare your functions by letting the architicture lead you:
Guide to app architecture
ui layer
state holders and ui state
Do you think this is the best way of doing what I want?
i am not very sure that i got exactly what your app do, but it seems like you want to re-order the elements of recycle view depending on the ui event (click) or data change (deleting or adding new element), now you have two choices:
if the order is very importnat to you that much you want to keep it even if the app has been destroyed
then you have to add a field in the room entity represent the ordering (let us call it order) and whenever the user click on the recycle view you have to update the rooms field "order" which is "flow" or "liveData" or any observable type, that will tell the view model that there is a changing in the data, now the view model have to re-order the new data by the field "order" and pass it to the recycle view to show it.
if your app do not have to save the order changes after the app been destroyed
then you can simply do that:
create list which is called "orderedList" you will put the list items in it by the right order, and another list called "unorderlist" which have getAllLists
for the first case where the ordering is being changed by user click, you
can declare a function in viewModel then use it in the ui
controller (your activity or fragment), so whenever the list item is
clicked this function just re-order the orderedList elements ( which
is observable, so the changes reflect on the ui ) just by change the
clicked item position to the front of the list.
for the second case where the ordering changes by data changes like
add or delet a list item in the database, then you have to compare
the legnth of orderlist and unorderlist legnth, if unorderList is
longer then it is an add situation else it is a delete situation, in
adding case just add the last item of unorderList to the orderList,
else you have to check the deleted item and delete it from
orderList.

Is there any way to observe specific actions on database using Room?

This docs provide a way to observe data stored in database. But this is too generic. This emits a new value whenever any changes occur to that table. Using this to update recyclerView means, on every update I have to replace old dataset by new one and call notifyDatasetChanged on the adapter. But instead is there any to specifically get updates like onRowInserted, onRowUpdated and onRowDeleted which returns only the data in the row being modified, as this helps me in making specific notifyItemInserted, notifyItemChanged and notifyItemRemoved calls to the adapter.

Get event when replacing node with the same value?

is it possible to get an event in a Listener when I replace value of a node with the same value? seams like if firebase notice that the value is the same no event accures..:s
The Firebase Database synchronizes state between clients. If a write operation doesn't change the state, there is nothing to synchronize to the other listening clients.
In simple code:
ref.setValue(1);
ref.setValue(1); // won't trigger listeners
ref.setValue(2); // will trigger active listeners
ref.setValue(2); // won't trigger listeners
It sounds like you want to instead pass messages between clients. This is totally feasible, but means that you should model your data differently. Instead of storing the value in your database, store the fact that the client wrote a value.
In simple code:
ref.push(1);
ref.push(1);
ref.push(2);
ref.push(2);
In this last sample each write will trigger listeners on ref, since each write is new.
This is a common pattern: instead of storing the final state, you're storing the state changes. It essentially similar the mechanism behind oplogs in databases and many other systems.
Because nothing happens there is no event that is triggered. What can you do in stead, is to check the value before you are setting it.
if(myValue.equals(firebaseValue)) {
//do something
} else {
//do something else
}
Hope it helps.

Firebase Android addChildEventListener explanation

I need some clear explanation with addChildEventListener and Query event binding.
I use firebase in my android app. In the onCreate() method of my activity, I create something like this...
fiDbQuery = fiDbRef.child("users").orderByChild("name");
fiDbQuery.addChildEventListener(// listener //);
... where fiDbQuery is a Query instance in the activity (global var) and fiDbRef is a DatabaseReference instance in the activity too, where I already set the initial value.
all is well, when activity first loaded, all the users data are loaded and shown. But then, I have some button to sort this data according to users field, either by email, age, name, etc.
and in those buttons onClickevent listener, I do something like this... (this one is the sort by age button)
fiDbQuery = fiDbRef.child("users").orderByChild("age");
... and I didn't provide the addChildEventListener function because it is already "added" on onCreate() method, right? The data aren't loaded, but if I add the addChildEventListener function it works again.
My question is, is it save to use multiple addChildEventListener into one Query, or is there any performance issues with that? All I want to accomplice is reusing the fiDbQuery instance without the need to add addChildEventListener every single time I modify the fiDbQuery.
Thank You for your help.
EDIT:
all those query I make use the exact same listener. Only one listener for all those query which populate a listView.
You don't need to add the addChildEventListener again. What you need to do, is to change the logic of your actions a little bit.
First define all your queries like this:
nameQuery = fiDbRef.child("users").orderByChild("name");
ageQuery = fiDbRef.child("users").orderByChild("age");
//and so on
To solve your problem, you only need to use an if else-if statement which sounds like this:
Query query;
if(nameButton.isClicked()) {
query = nameQuery;
} else if(ageButton.isClicked()) {
query = ageQuery;
}
query.addChildEventListener( // listener. //);
This means that according on which button the click was made, you are using the desired query. With this code, you just use the addChildEventListener once.
Hope it helps.

Add a service to my android app to get notifications whenever a fire base child is added [duplicate]

I have a node in Firebase getting continually updated with information from a logfile. The node is lines/ and each child of lines/ is from a post() so it has a unique ID.
When a client first loads, I want to be able to grab the last X number of entries. I expect I'll do this with once(). From then on, however, I want to use an on() with child_added so that I get all new data. However, child_added gets all data stored in the Firebase and, after the initial setup, only want the new stuff.
I see that I can add a limitToLast() on the on(), but, if I say limitToLast(1) and a flood of entries come in, will my app still get all the new entries? Is there some other way to do this?
You need to include a timestamp property and run a query.
// Get the current timestamp
var now = new Date().getTime();
// Create a query that orders by the timestamp
var query = ref.orderByChild('timestamp').startAt(now);
// Listen for the new children added from that point in time
query.on('child_added', function (snap) {
console.log(snap.val()
});
// When you add this new item it will fire off the query above
ref.push({
title: "hello",
timestamp: Firebase.ServerValue.TIMESTAMP
});
The Firebase SDK has methods for ordering, orderByChild() and methods for creating a range startAt(). When you combine the two you can limit what comes back from Firebase.
I think there is a problem in #David East's solution. He is using the local timestamp which may cause problem if the time is not accurate in client device. Here is my suggested solution (iOS Swift):
Using observeSingleEvent to get the complete data set
Then returned it in reversed order by reversed()
Get the last timestamp by for example data[0].timestamp
Using queryStarting for timestamp
self._dbref.queryOrdered(byChild: "timestamp").queryStarting(atValue: timestamp+1)
.observe(.childAdded, with: {
snapshot in
print(snapshot.value)
})
You have the right idea. child_added should be called only for the new nodes. Without source code it's hard to tell why you get all the data in your child_added event.
You can check the chat demo app to see how they load new chat messages. The use case sounds similar.
https://github.com/firebase/firechat/blob/master/src/js/firechat.js#L347
Here's temporary but quick solution:
// define a boolean
var bool = false;
// fetch the last child nodes from firebase database
ref.limitToLast(1).on("child_added", function(snap) {
if (bool) {
// all the existing child nodes are restricted to enter this area
doSomething(snap.val())
} else {
// set the boolean true to doSomething with newly added child nodes
bool = true;
}
});
Disadvantage: It will load all the child nodes.
Advantage: It will not process existing child nodes but just the newly added child nodes.
limitToLast(1) will do the work.

Categories

Resources