I have a for loop that is creating seats. I am trying to check if the seat was already registered(booked) in our database, so as I initiate the seat I want to get into my database and check if its already there, so I put in a method called look within the two for loops, like this
for (i = 0; i < maxRow; i++) {
for (j = 0; j < maxColumn; j++) {
final SeatMo seat = new SeatMo();
seat.row = i;
seat.column = j;
seat.status = 1;
look(seat,i,j)
seatTable[i][j] = seat;
}
}
The method look is where the reference is, when I saved the seat in the database, I named the child by the specific seat that was selected e.g col:2 row:3, here is the look method
private void look(final SeatMo seat, final int a, final int b) {
databaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("col:" + i + " row:" + j)) {
seat.status = 0;
} else {
seat.status = 1;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
In my mind I want it to check for every seat as the seat is being initiated, but for some reason which I hope you may find in the code about, when the method look is called, it skips the reference(databaseRef completely). My question is, what could be causing the reference to be skipped and how can I make sure it does not get skipped?
The databaseRef is declared in the Oncreate method, it is a field
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seats);
if(getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
currUser = FirebaseAuth.getInstance().getCurrentUser();
Intent callingIntent = getIntent();
maxC = Integer.valueOf(callingIntent.getStringExtra("col"));
maxR = Integer.valueOf(callingIntent.getStringExtra("row"));
decks = Integer.valueOf(callingIntent.getStringExtra("deck"));
fare = Double.valueOf(callingIntent.getStringExtra("fare"));
driver = callingIntent.getStringExtra("id");
destination = callingIntent.getStringExtra("dest");
databaseRef = FirebaseDatabase.getInstance().getReference("coach-drivers" + "/" + driver + "/" + "clients" );
initSeatTable(maxC,maxR);
selectedSeats = new ArrayList<>();
mMovieSeatView1= (MovieSeatView) findViewById(R.id.seat_view_one);
deck = (Spinner) findViewById(R.id.top_bottom);
mMovieSeatView1.setSeatTable(seatTable);
mMovieSeatView1.setPresenter(this);
}
The ref has the right route
Have tried changing the route to the ref like this
databaseRef = FirebaseDatabase.getInstance().getReference().child("coach-drivers").child(driver).child("clients");
still does not get to the onDataChange() and onCancel method
This is the Json structure of my database
{
"coach-drivers": {
"iiiiiiiiiiiiiii": {
"clients": {
"col:3 row:2": "one",
"col:3 row:1:"one",
"col:1 row:3" : "one"
}
}
}
}
the iiiiiiiiiii is for the driverId, represented by driver field initiated in OnCreate method
SOLVED BY USING CLOUD FIRESTORE, STILL DON'T KNOW WHY FIREBASE REFERENCE WAS BEING SKIPPED THOUGH
To solve this, move the logic of checking if the seat was already registered inside onDataChange() method. You cannot simply use seat.status outside that method because the value will be always null due the asynchronous behaviour of the method.
Having all the logic inside that method, will solve the issue. If want to use the value outside, please see my answer from this post.
Put your reference inside your look method
Also keep seatTable[i][j] = seat in OnDataChange as show below:
private void look(final SeatMo seat, final int a, final int b) {
databaseRef = FirebaseDatabase.getInstance().getReference("coach-drivers" + "/" + driver + "/" + "clients" );
databaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("col:" + i + " row:" + j)) {
seat.status = 0;
} else {
seat.status = 1;
}
seatTable[i][j] = seat;
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Related
This question already has answers here:
How to check a certain data already exists in firestore or not
(1 answer)
Why does my function that calls an API or launches a coroutine return an empty or null value?
(4 answers)
How to return a DocumentSnapShot as a result of a method?
(2 answers)
Closed 1 year ago.
I am able to read the data from my firestore database, but I am not able to wait in the code till the entire data is loaded. So what is happening is that my code executes forward even before the data required is actually loaded. I want to know how can I wait while reading data from firestore, and once the data is fetched, then only make the other code execute. PFB my code snippet.
public void getFoodMenu(String clientID){
clientFullMenu.clear();
DocumentReference docRef = mDatabase.collection("MenuDetails").document(clientID);
docRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if(documentSnapshot.exists()){
String sMenuCurrency = documentSnapshot.getString("menu_currency");
colRefMenuType = docRef.collection("MenuType");
colRefMenuType.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
List<DocumentSnapshot> menuTypeDocuments = queryDocumentSnapshots.getDocuments();
for(int i=0; i<menuTypeDocuments.size();i++){
DocumentSnapshot menuTypeDoc = menuTypeDocuments.get(i);
String sMenuType = menuTypeDoc.getId();
String sSubMenuPriority = menuTypeDoc.getString("priority");
Log.i("XXXX","document::"+menuTypeDoc.getId()+", priority::"+sSubMenuPriority);
colRefMenuItems = colRefMenuType.document(sMenuType).collection("MenuItems");
colRefMenuItems.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
List<DocumentSnapshot> menuItemDocuments = queryDocumentSnapshots.getDocuments();
for(int j=0;j<menuItemDocuments.size();j++){
DocumentSnapshot menuItemDoc = menuItemDocuments.get(j);
String sFoodItemID = menuItemDoc.getId();
String sFoodItemPriority = menuItemDoc.getString("food_item_priority");
String sFoodItem = menuItemDoc.getString("food_item");
String sFoodItemDesc = menuItemDoc.getString("food_item_description");
String sImageUrl = menuItemDoc.getString("food_item_image_location");
String sFoodItemPrice = menuItemDoc.getString("food_item_price");
Log.i("XXXX","FoodItem::"+menuItemDoc.getId()+", priority::"+sFoodItemPriority);
boolean bMenuType = false;
FoodMenu menu = new FoodMenu();
menu.sFoodItemID = sFoodItemID;
menu.sFoodItem = sFoodItem;
menu.sFoodItemDesc = sFoodItemDesc;
menu.sFoodMenuCurrency = sMenuCurrency;
menu.iFoodItemPrice = Integer.parseInt(sFoodItemPrice);
menu.sImageUrl = sImageUrl;
menu.sMenuItemPriority = sFoodItemPriority;
//code to add the item under its corresponding food menu type (viz BREAKFAST, LUNCH, DINNER) in case it already exists
for (int i = 0; i < clientFullMenu.size(); i++) {
Log.i("MainActivity","clientFullMenu.get(i).sMenuType:" + clientFullMenu.get(i).sMenuType+" ,sMenuType:"+sMenuType);
if (clientFullMenu.get(i).sMenuType.equalsIgnoreCase(sMenuType)) {
clientFullMenu.get(i).subFoodMenu.add(menu);
bMenuType = true;
}
}
//code to add a new arraylist of food menu type (viz BREAKFAST, LUNCH, DINNER) in case it doesn't exist already
if (!bMenuType) {
ClientFullMenu clientSubMenu = new ClientFullMenu();
clientSubMenu.sMenuType = sMenuType;
clientSubMenu.sMenuPriority = sSubMenuPriority;
ArrayList<FoodMenu> subFoodMenu = new ArrayList<FoodMenu>();
subFoodMenu.add(menu);
clientSubMenu.subFoodMenu = subFoodMenu;
clientFullMenu.add(clientSubMenu);
Log.i("XXXX","Final clientFullMenu.size()1:" + clientFullMenu.size()); //it prints the correct size
}
}
}
});
}
}
});
}
}
});
Log.i("XXXX","Final clientFullMenu.size()2:" + clientFullMenu.size()); //It prints size as 0
}
Need to Do:
Basically i want Firestore => collection "order" => docs having customerid and productid on each doc => onSuccess => add to OrderPOJOList => call getCustomerName() then getProductName() => get Names in order => add to respective ArrayList => in end combine all data from three arraylist (OrderPOJOList, CustomerName, ProductName) to CurrentOrderPOJOList => set to Adapter.
Problem:
the two listeners in getCustomerName() & getProductName() runs asynchronously and adds Name to arrayList randomly... all i want is to show data on Adapter in order but sometimes names get exchange on list due to listners running asynchronously.
What should i do to get my customer and product names from firestore in sequence to display?
public class CurrentOrders extends AppCompatActivity {
private List<CurrentOrdersPOJO> currentOrdersPOJOList;
private List<OrderPOJO> orderPOJOList;
private FirebaseFirestore firebaseFirestore;
private String DocId, Area, cname, pname;
private OrderPOJO orderPOJO;
private CurrentOrdersPOJO currentOrdersPOJO;
private int count = -1, count1 = -1, i;
private RecyclerView recyclerView;
private List<String> customerName, productName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_current_orders);
//Current User Unique ID
DocId = getIntent().getStringExtra("DocumentId");
Area = getIntent().getStringExtra("Area");
Log.w("ReachedCurrentOrders", "Doc Id: " + DocId + "\nArea: " + Area);
currentOrdersPOJOList = new ArrayList<>();
customerName = new ArrayList<String>();
productName = new ArrayList<String>();
orderPOJOList = new ArrayList<>();
recyclerView = findViewById(R.id.activity_current_order_recyclerView);
firebaseFirestore = FirebaseFirestore.getInstance();
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
firebaseFirestore.collection("order")
.whereEqualTo("area", Area)
.whereEqualTo("status", "active")
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(final QuerySnapshot queryDocumentSnapshots) {
if (!queryDocumentSnapshots.isEmpty()) {
for (final QueryDocumentSnapshot queryDocumentSnapshot : queryDocumentSnapshots) {
count++;
}
for (final QueryDocumentSnapshot queryDocumentSnapshot : queryDocumentSnapshots) {
orderPOJO = queryDocumentSnapshot.toObject(OrderPOJO.class);
orderPOJOList.add(orderPOJO);
Log.d("Tagging", "The Customer UID: " + orderPOJO.getC_uid() + "\nThe Product Doc ID: " + orderPOJO.getP_docid());
count1++;
if (count == count1) {
getCustomerName();
}
}//endof for loop
} else {
Toast.makeText(CurrentOrders.this, "No Orders in Your Area", Toast.LENGTH_SHORT).show();
Log.d("CurrentOrder", "Exception Here");
}
}
});
}//endofOnCreate
public void getCustomerName() {
count1 = -1;
//Getting Customer Name from ID
for (i = 0; i <= count; i++) {
firebaseFirestore.collection("customer").document(orderPOJOList.get(i).getC_uid()).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
cname = documentSnapshot.getString("name");
customerName.add(cname);
count1++;
if (count1 == count) {
getProductName();
}
} else {
Log.d("CurrentOrders", "Exception Here" + documentSnapshot.exists());
}
}
});
}
}//end of function
public void getProductName() {
count1 = -1;
//Product Getting Name
for (i = 0; i <= count; i++) {
firebaseFirestore.collection("product").document(orderPOJOList.get(i).getP_docid()).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
pname = documentSnapshot.getString("name");
productName.add(pname);
count1++;
if (count1 == count) {
callAdapter();
}
} else {
Log.d("CurrentOrders", "Exception Here" + documentSnapshot.exists());
}
}
});
}
}//endofFunction
public void callAdapter() {
for (int i = 0; i <= count; i++) {
currentOrdersPOJO = new CurrentOrdersPOJO(customerName.get(i), orderPOJOList.get(i).getComplete_address(),
productName.get(i), orderPOJOList.get(i).getQuantity(), orderPOJOList.get(i).getStatus(), orderPOJOList.get(i).getArea(), orderPOJOList.get(i).getO_date());
currentOrdersPOJOList.add(currentOrdersPOJO);
}
recyclerView.setAdapter(new CurrentOrdersAdapter(currentOrdersPOJOList, CurrentOrders.this));
}//endofFunction
}//endofclass
[screenshot of an activity showing list that varies everytime][1]
[1]: https://i.stack.imgur.com/X48JF.jpg
A similar question has been asked on another thread, it seems that you can synchronously return data because the method itself is a task, you could try to use the Taks.await(task) method to wait for the operation to end maybe that's the answer you're looking for.
I Have solved this problem by using mentioned solution by #Ricardo above AND combining the solution with using Asynctask(Background Thread) as it was first giving IllegalStateException because of calling Tasks.await(task) on Main UI Thread.
So, Use: Tasks.await(task) on Aysnctask(Background Thread)
I'm running a for loop and saving data on firebase inside it.
Here's my code:
private int counter = 1;
pProgress.setMessage("Posting...");
pProgress.show();
pProgress.setCancelable(false);
for (int i=0; i<imageArray.size(); i++) {
Uri file = Uri.fromFile(new File(imageArray.get(i).toString()));
String key = database.getReference().push().getKey();
UploadTask uploadTask = storage.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(key).child("product_image").putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
counter++;
if (counter == imageArray.size()) {
Toast.makeText(getBaseContext(), "successfully posted!", Toast.LENGTH_SHORT).show();
imageView.setImageResource(0);
pDescription.setText("");
pDuration.setText("");
pPrice.setText("");
label.setText("Label");
if (pProgress.isShowing()) {
pProgress.dismiss();
}
}
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
#SuppressWarnings("VisibleForTests")
Uri downloadUrl = taskSnapshot.getDownloadUrl();
imageUrls.add(downloadUrl.toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDescription").setValue(pDescription.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDuration").setValue(pDuration.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pPrice").setValue(pPrice.getText().toString());
if (imageUrls != null) {
for (int i=0; i<imageUrls.size(); i++) {
Log.d("imageUrlsSize", String.valueOf(imageUrls.size()));
String idtwo = database.getReference().push().getKey();
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child(idtwo).child("imageUrl").setValue(downloadUrl.toString());
if (imageUrls.size() > 0) {
imageUrls.clear();
}
}
}
}
});
}
I want to show a ProgressDialog and dismiss it when the data is uploaded successfully. Similarly, I want to clear the EditText fields and ImageView too.
How can I figure out imageArray has ended so that I can dismiss ProgressDialog and clear edittext as well as imageview?
Please let me know.
One way would be to check the count in your callbacks. You would check it in onFailure and onSuccess. Something like this
for (int i = 0; i < imageArray.size(); i++) {
final int currentCount = i + 1;
/** code **/
onSuccess() {
if (currentCount == imageArray.size()) // do something
}
}
You may also need to declare imageArray as final. This has the disadvantage that you will know that the last element has been processed, but you will have no idea if there are other request still pending. A better approach would be to use a member field in your class e.g.
class YourClass{ private int currentCount = 0; }
and you would again count this in your callbacks e.g.
for (int i = 0; i < imageArray.size(); i++) {
onSuccess() {
currentCount++;
if (currentCount == imageArray.size()) // do something
}
}
Beeing a Real-time database there is no cetain moment in which we can say that we have loaded all the reconars from the database or that an ArrayList has reached it's last element. This happening because there is a possibility that in every moment something can change, i.e. an item/items can be added or deleted. This is the way in which Firebase was built.
But a short answer to your question, first move the declaration of your imageUrls ArrayList inside the onSuccess() method otherwise will be null due the asynchronous behaviour of this method. Second, define a variable in your class named count and increase the value of it each time onSuccess() method is called and compare it with the size of your list like this:
int count = 0;
onSuccess() {
count++;
if(count == imageArray.size() : do somethig ? do something else)
}
You are handling async tasks so you need to encapsulate your job and work with a Queue and callbacks. Try something like that:
class Job{
private Runnable completeCallback;
private String key;
private Uri file;
public Job(String key, Uri file) {
this.key = key;
this.file = file;
}
public void setCompleteCallback(Runnable completeCallback) {
this.completeCallback = completeCallback;
}
void doWork(){
UploadTask uploadTask = storage.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(key).child("product_image").putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
completeCallback.run();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
#SuppressWarnings("VisibleForTests")
Uri downloadUrl = taskSnapshot.getDownloadUrl();
imageUrls.add(downloadUrl.toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDescription").setValue(pDescription.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDuration").setValue(pDuration.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pPrice").setValue(pPrice.getText().toString());
if (imageUrls != null) {
for (int i=0; i<imageUrls.size(); i++) {
Log.d("imageUrlsSize", String.valueOf(imageUrls.size()));
String idtwo = database.getReference().push().getKey();
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child(idtwo).child("imageUrl").setValue(downloadUrl.toString());
if (imageUrls.size() > 0) {
imageUrls.clear();
}
}
}
completeCallback.run();
}
});
}
}
class Queue {
ArrayList<Job> jobs = new ArrayList<>();
private int total;
public void execute(){
total = imageArray.size();
for (int i=0; i<imageArray.size(); i++) {
Uri file = Uri.fromFile(new File(imageArray.get(i).toString()));
String key = database.getReference().push().getKey();
Job job = new Job(key, file);
job.setCompleteCallback(new Runnable() {
#Override
public void run() {
jobs.remove(job);
updateUi();
}
});
jobs.add(job);
}
for (int i = jobs.size() - 1; i >= 0; i--) {
Job job = jobs.get(i);
job.doWork();
}
}
private void updateUi() {
Log.d("UI", "Completed " + jobs.size() + "/" + total);
}
}
I figured it out with the help of Murat K's answer.
I just shifted this code
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDescription").setValue(pDescription.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pDuration").setValue(pDuration.getText().toString());
database.getReference().child(AccessToken.getCurrentAccessToken().getUserId()).child(id).child("pPrice").setValue(pPrice.getText().toString());
out of the for loop and now everything is working as expected.
I'm new to Android and Firebase environment but I'm working on it !
I'm working on an Android app and I need to read some values related to a child within a Firebase database. After this initial read, I need to modify / update these values and write them to the same child.
public class MainActivity extends Activity {
public static class Shoe extends JSONObject {
private String name;
private int size;
Shoe(){
// Default constructor required for calls to
// DataSnapshot.getValue(Shoe.class)
}
Shoe( String nm, int sz) { this.name = nm; this.size = sz; }
public int getSize() { return this.size; }
public void setSize(int sz) { this.size = sz; }
public String getName() { return this.name;}
public void setName(String nm) {this.name = nm; }
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.setPersistenceEnabled(true);
DatabaseReference myRefTarget = database.getReference("target");
Shoe obj1 = new Shoe("item ID 1", 99);
Shoe obj2 = new Shoe("item ID 2", 1000);
final Shoe obj_old = new Shoe();
Shoe obj_new = new Shoe();
DatabaseReference myRefDeviceA = myRefTarget.child("deviceA").getRef();
myRefDeviceA.keepSynced(true);
myRefDeviceA.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
obj_old.setName( dataSnapshot.getValue(Shoe.class).getName());
obj_old.setSize( dataSnapshot.getValue(Shoe.class).getSize());
Log.d(TAG_CLOUD, "from onDataChange: deviceA = " + obj_old.getName() + ", " + obj_old.getSize());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
// HERE
Log.d(TAG_CLOUD, "Name = " + obj_old.getName() + ", Size = " + obj_old.getSize());
}
the issue I got is that the read operation is asynchronously done..
D/FROM CLOUD: Name = null, Size = 0
D/FROM CLOUD: from onDataChange: deviceA = item ID 1, 99
how can adapt / modify the source code in such way that first "read" to give me values different than null and '0' ? "HERE" line
eg.
Name = item ID 1 Size = 99
Thank you.
You don't suppose to perform networking operations on the UI thread.
If you want to display the data in the activity, you should show a loading dialog in the onCreate method, and then after fetching the data close the dialog and update the activity view
I have a RideList class that is called from an Activity class that retrieves data from a Firebase database. However, when I debug my program the code within my addValueEventListener is never being reached.
public class RideList {
private ArrayList<Ride> listofRides;
public Firebase myFirebase = new Firebase("https://luminous-torch-1510.firebaseio.com/rides");
Context context;
public RideList(Context context) {
this.context = context;
this.listofRides = new ArrayList <Ride>();
}
public ArrayList<Ride> getRides() {
Firebase.setAndroidContext(context);
// Attach an listener to read the data at our rides reference
Query queryRef = myFirebase.orderByChild("timePosted");
try {
queryRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
System.out.println("There are " + snapshot.getChildrenCount() + " rides");
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
String rideString = postSnapshot.getValue().toString();
String[] rideA = rideString.split(" ");
String value;
for (int i = 0; i < rideA.length - 1; i++) {
rideA[i] = rideA[i].substring(rideA[i].indexOf("=") + 1);
rideA[i] = rideA[i].substring(0, rideA[i].indexOf(","));
}
rideA[rideA.length - 1] = rideA[rideA.length - 1].substring(rideA[rideA.length - 1].indexOf("=") + 1);
rideA[rideA.length - 1] = rideA[rideA.length - 1].substring(0, rideA[rideA.length - 1].indexOf("}"));
double numOfPassengers = Double.valueOf(rideA[6]);
double fare = Double.valueOf(rideA[4]);
double distance = Double.valueOf(rideA[3]);
String origin = rideA[7];
String destination = rideA[2];
double maxPassengers = Double.valueOf(rideA[5]);
String departTime = rideA[1];
String arrivalTime = rideA[0];
String timePosted = rideA[8];
String title = rideA[9];
String type1 = rideA[10];
boolean type;
if (type1.equals("offer"))
type = false;
else
type = true;
Ride ride = new Ride(numOfPassengers, fare, distance, origin, destination, maxPassengers, departTime, arrivalTime,
timePosted, title, type);
listofRides.add(ride);
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});
Thread.sleep(2000);
} catch (InterruptedException e) {
return null;
}
return listofRides;
}
}
This code is being called from an OnCreate function of an Activity class. Any idea on why the listener code is never being entered/executed?
Edit: Here is the code on how this function is being called in the activity class.
list = (ListView) findViewById(R.id.showrides_listView);
Firebase.setAndroidContext(this);
RideList rl = new RideList(this);
ArrayList arrayList = rl.getRides();
// Adapter: You need three parameters 'the context, id of the layout (it will be where the data is shown),
// and the array that contains the data
ArrayAdapter adapter = new ArrayAdapter<Ride>(getApplicationContext(), android.R.layout.simple_spinner_item, arrayList){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = (TextView) view.findViewById(android.R.id.text1);
text.setTextColor(Color.BLACK);
return view;
}
};
// Here, you set the data in your ListView
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
FloatingActionButton myFab = (FloatingActionButton) findViewById(R.id.showrides_fab);
myFab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startCreateRideActivity();
}
});
Your data is being loaded asynchronously (and after that continuously synchronized) from Firebase. Putting a Thread.sleep() in there is not going to change that fact.
You can easily see what happens if you add a few log statements:
public ArrayList<Ride> getRides() {
Query queryRef = myFirebase.orderByChild("timePosted");
try {
System.out.println("Adding listener");
queryRef.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
// THIS CODE IS CALLED ASYNCHRONOUSLY
System.out.println("Got data from Firebase");
}
public void onCancelled(FirebaseError firebaseError) {
}
});
System.out.println("Starting sleep");
Thread.sleep(2000);
} catch (InterruptedException e) {
return null;
}
System.out.println("Returning rides");
return listofRides;
}
The output is likely:
Adding listener
Starting sleep
Returning rides
Got data from Firebase
You're trying to make an asynchronous process synchronous, which is a recipe for headaches and a bad user experience. Instead of writing up a solution here, I'll link to an answer I wrote 15 minutes ago to the same problem: Retrieving ArrayList<Object> from FireBase inner class