Retrieve random object from ArrayList - java

The method below is the method I am using to populate my array. However I wish to return a random deals_informationobject from my ArrayList of type Deals_Information but am not quite sure how.
public void populateArray() {
databaseReference.child("FruitDeals").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> children = dataSnapshot.getChildren();
final ArrayList<Deals_Information> myArray = new ArrayList<>();
for (DataSnapshot child : children) {
Deals_Information deals_information = child.getValue(Deals_Information.class);
myArray.add(deals_information);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}

Use Random to get a random int from the range of 0 and the size-1 of your collection.
Since Java 1.7, the recommended Random implementation is ThreadLocalRandom.
private int randomInt(final int from, final int to) {
return ThreadLocalRandom.current().nextInt(from, to);
}

Because ArrayLists have a get() function, the way to do this is to first generate a random number by using the math.random() function, and then use the get() function of your ArrayList to call the object at that randomly generated index.

Related

How to update an array item in the Realtime Database from within Android

How to access a child inside real time database array child?
String count = item_count.getText().toString();
firebaseDatabase = FirebaseDatabase.getInstance();
reference = firebaseDatabase.getReference()
reference.child("beverages").child(????)
.child("item_count").setValue(count);
this is my code but I don't know what should I put in the question
marks.
]1
You can get the item_count by using foreach loop inside the onDataChange method.
Lets say this is your model class for your Beverage.
public class Beverage {
private long item_count;
private String item_img;
private String item_name;
public Beverage beverage(long itemCount){
this.item_count = itemCount;
//and do others also...
}
//Here your get set...
}
Here you get the data as arrayList
reference.child("beverages").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
ArrayList<Beverage> beveragesList = new ArrayList<Beverage>();
//Get children
for (DataSnapshot snapShot : dataSnapshot.getChildren()) {
if (snapShot.exists()) {
final Beverage beverage = snapShot.getValue(Beverage.class);
if (beverage != null){
//Her you got the data as array list
beverageList.add(beverage);
}
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.i("???","Db error: " + databaseError.getMessage());
}
});
You need to put child of beverages here like 0,1,2, or 3.
reference.child("beverages").child("3").child("item_count").setValue(count);

Index:0 Size:0 when fetching item from firebase [duplicate]

This question already has answers here:
getContactsFromFirebase() method return an empty list
(1 answer)
Setting Singleton property value in Firebase Listener
(3 answers)
Closed last year.
I am trying to fetch a value from firebase like so:
private String getVCount(String mPath) {
ArrayList<String> strings = new ArrayList<>();
FirebaseDatabase.getInstance().getReference("cars").child(mPath).child("maserati")
.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull #NotNull Task<DataSnapshot> task) {
if(task.isSuccessful()){
strings.add(task.getResult().getValue().toString());
}else{
strings.add("0");
}
}
});
Log.d("mString", String.valueOf(strings.size()));
return strings.get(0);
}
I double checked the path, and even added an else condition just to make it so that the strings array list has at least one value in it.
The value in the database does exist, and does not exist in some cases--hence the else statement to add a default value of 0. I'm not sure if this is the correct way to do that though.
Additionally, I'm still getting the error: Index: 0 Size: 0--meaning that the strings array list is empty.
Any idea why this may be so?
Thanks.
Getting data from Firebase Realtime Database is an async task. So,
Log.d("mString", String.valueOf(strings.size()));
return strings.get(0);
might be getting called before the code inside addOnCompleteListener.
If you want to have your getVCount to have a way to return the result, one way to do this is by creating your own callback like this:
public interface Callback {
void onCallback(String result);
}
private void getVCount(String mPath, Callback callback) {
ArrayList<String> strings = new ArrayList<>();
FirebaseDatabase.getInstance().getReference("cars").child(mPath).child("maserati")
.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull #NotNull Task<DataSnapshot> task) {
if(task.isSuccessful()){
strings.add(task.getResult().getValue().toString());
}else{
strings.add("0");
}
Log.d("mString", String.valueOf(strings.size()));
callback.onCallback(strings.get(0));
}
});
}
And call it like this:
getVCount(new Callback() {
#Override
public void onCallback(String result) {
Log.d(TAG, result);
}
});

get count of all childs with a specific value in firebase

im trying to get the count of all childs with a specific value.
users.orderByChild("isOnline").equalTo("1").
addListenerForSingleValueEvent(
new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot p1)
{
t(""+p1.getChildrenCount());
}
#Override
public void onCancelled(DatabaseError p1)
{
}
});
but the problem is there is a unique child among each users and isOnline childs.
The values of your isOnline node are numbers, so you need to compare them to a number foo:
users.orderByChild("isOnline").equalTo(1)...

Problems with array in addChildEventListener (Firebase)

Integer scores[] = new Integer[10];
int count = 0;
I have some data that I want to put into array. I put it in onChildAdded, but if I need to get the data from the array out of the onChildAdded, console shows "null".
If I will try to get the data of array into onChildAdded, it will be
success
data.child("scores").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
count++;
scores[count] = dataSnapshot.getValue(Integer.class);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
int i = scores[1];
IMPORTANT MOMENT
For example, If I will use operation FOR
for (int i = 0; i < 10; ++i) {
scores[i] = i;
}
int i = scores[3];
i will not be null
Firebase APIs are asynchronous, meaning that each one of those methods: onChildAdded(), onChildChanged() etc, return immediately after it's invoked, and the callback from the Task it returns, will be called some time later. There are no guarantees about how long it will take. So it may take from a few hundred milliseconds to a few seconds before that data is available. Because that method returns immediately, the scores array has not have been populated from the callback yet and that's why is empty.
Basically, you're trying to use a value synchronously from an API that's asynchronous. That's not a good idea. You should handle the APIs asynchronously as intended.
A quick solve for this problem would be to move the following lines of code:
for (int i = 0; i < 10; ++i) {
scores[i] = i;
}
int i = scores[3];
Inside the onChildAdded() method, where the data is available.
If you need to loop your score array outside the callback, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Pagination not working using Firebase database

I have a problem with firebase pagination.
I have table posts and this is an example structure:
and I want to get only 10 post every time, here is my code page is 0:
#NonNull
#CheckResult
public Single<DataSnapshot> getData(#NonNull DatabaseReference ref, int page) {
return Single.create(emitter -> {
ref.orderByChild("timestamp")
.startAt(page * 10)
.limitToFirst(10);
final ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!emitter.isDisposed()) {
emitter.onSuccess(dataSnapshot);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
if (!emitter.isDisposed()) {
emitter.onError(databaseError.toException());
}
}
};
ref.addListenerForSingleValueEvent(listener);
});
}
and here is the result
Why I have list size equals 20 not 10? p.s. limit to first or limit to last it's no difference with the result
Calling startAt(), limitToFirst() and similar methods on a DatabaseReference returns a new Query object. You need to keep a reference to that Query and attach your listeners to that:
Query query = ref.orderByChild("timestamp")
.startAt(page * 10)
.limitToFirst(10);
query.addListenerForSingleValueEvent(listener);

Categories