0

I have an Activity that needs to pull data from FireBase and put it in a listView. When I debug within the function and print the length of the list whilst filling it, everything is fine and it fills up properly. But when I call the function at the start of the activity in order to fill the list and then refresh the adapter the list shows up as empty for some reason. I even tried sleeping the main thread but that doesn't help. The activity:

public class OrdersActivity extends AppCompatActivity {

    FirebaseDatabase database = FirebaseDatabase.getInstance("https://computerstorefb-default-rtdb.firebaseio.com/");
    DatabaseReference myRef = database.getReference("");

    OnSuccessListener<Void> listener;

    static ArrayList<Order> ordersList = new ArrayList<Order>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_orders);



        Button back = (Button)findViewById(R.id.btnOrdersBack);
        ListView lvOrders = findViewById(R.id.lvOrders);
        TextView proLabel = findViewById(R.id.proLabel);

        ordersList.clear();
        getOrdersFromDB(listener);


        SmsManager mySmsManager = SmsManager.getDefault();


        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        Log.d("size",ordersList.size()+"");     // 0 

        ArrayAdapter<Order> ordersAdapter = new ArrayAdapter<Order>(OrdersActivity.this, android.R.layout.simple_list_item_1,ordersList);
        lvOrders.setAdapter(ordersAdapter);

        Log.d("size",ordersList.size()+"");     //0



        listener = new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void unused) {
                ArrayAdapter<Order> ordersAdapter = new ArrayAdapter<Order>(OrdersActivity.this, android.R.layout.simple_list_item_1,ordersList);
                lvOrders.setAdapter(ordersAdapter);
                Toast.makeText(OrdersActivity.this, "Done!", Toast.LENGTH_SHORT).show();
            }
        };

        lvOrders.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

                Order o = OrdersActivity.ordersList.get(i);

                myRef.child("Orders").child(o.name+"").child("status").setValue("SHIPPED!");

                OrdersActivity.ordersList.clear();
                getOrdersFromDB(listener);


                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                ArrayAdapter<Order> ordersAdapter = new ArrayAdapter<Order>(OrdersActivity.this, android.R.layout.simple_list_item_1,ordersList);
                lvOrders.setAdapter(ordersAdapter);

                String message = "Hey " + o.name + "! your package from Igor's Computers had been shipped!";


                try {
                    mySmsManager.sendTextMessage(generatePhone(o.tel),null,message,null,null);
                }
                catch(Exception e){
                    Toast.makeText(OrdersActivity.this, "Can't send message!", Toast.LENGTH_SHORT).show();
                }

            }
        });







        back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }

The function that loads the data:

private void getOrdersFromDB(OnSuccessListener<Void> onSuccess){


        Query q = myRef.child("Orders");
        q.addListenerForSingleValueEvent(new ValueEventListener()
        {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot)
            {
                for (DataSnapshot dst : snapshot.getChildren())
                {

                    Order o = dst.getValue(Order.class);
                    if(!o.status.contains("SHIPPED")) {
                        OrdersActivity.ordersList.add(o);
                        Log.d("p","size: "+ordersList.size()+"");    //counts properly

                    }
                }
                if(onSuccess != null)
                {
                    onSuccess.onSuccess(null);
                }
            }
            @Override
            public void onCancelled(@NonNull @NotNull DatabaseError error)
            {

            }



        });


    }
Guy zvi
  • 77
  • 1
  • 6
  • Does this answer your question? [Why does my function that calls an API return an empty or null value?](https://stackoverflow.com/a/70178210/9473786) - the database call is asynchronous and putting a timed delay to wait for it is a terrible solution that blocks the UI thread. If the network is slow it won't be long enough and if the network is fast it makes the user wait unnecessarily – Tyler V Jun 12 '22 at 16:51
  • There is no way you can do that. Firebase API is asynchronous. So please check the duplicate to see how can you solve this using a callback. You might also be interested in reading this [resource](https://medium.com/firebase-tips-tricks/how-to-read-data-from-firebase-realtime-database-using-get-269ef3e179c5). – Alex Mamo Jun 13 '22 at 08:58

0 Answers0