0

I have this code which retrieves the information I need from the firebase database:

private void getname(){

    DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
    Query lastQuery = ref.child("ride_info").orderByKey().limitToLast(1);
    lastQuery.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot ds : dataSnapshot.getChildren()){
                String value0_float = ds.child("pickup").child("name").getValue(String.class);
                pickupName = String.valueOf(value0_float);
                
                
            }
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
            
        }
    });
}

and i have this:

public String getPickupName() {

    getname();
    String s = String.valueOf(pickupName);
    return s;

}

All of the above code is in the RideObject class.

This is the code there is in CardRequestAdapter Class to display the String in the textview mPickupName:

public View getView(int position, View convertView, ViewGroup parent){
    RideObject card_item = getItem(position);

    if (convertView == null){
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.item__card_request, parent, false);
    }



    TextView mDistance = convertView.findViewById(R.id.distance);
    TextView mTime = convertView.findViewById(R.id.time);
    CircularProgressBar mProgressBar = convertView.findViewById(R.id.circularProgressBar);

    mDistance.setText(card_item.getPickupName());
    mTime.setText(card_item.getCalculatedTime() + " min");


    final Handler ha=new Handler();
    ha.postDelayed(new Runnable() {

        @Override
        public void run() {
            //call function
            card_item.setTimePassed(card_item.getTimePassed() + (float)0.5);
            mProgressBar.setProgress(card_item.getTimePassed());

            if(card_item.getTimePassed() > 100){
                items.remove(card_item);

                notifyDataSetChanged();
            }

            ha.postDelayed(this, 50);

        }
    }, 50);

    return convertView;

}

}

The problem I have is that I cannot get the name I got from the Firebase database. Why is nothing displayed in the text view?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
gunara
  • 1
  • 2

1 Answers1

0

Data is loaded from Firebase asynchronously, since it may take some time. If you set some breakpoints or add some logging you'll likely see that mDistance.setText(card_item.getPickupName()); runs before pickupName = String.valueOf(value0_float), which means you're setting an empty string into the text view.

The rule to fix/prevent this is simple: any code that needs data from the database needs to be inside onDataChange or be called from there.

So something like:

DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Query lastQuery = ref.child("ride_info").orderByKey().limitToLast(1);
lastQuery.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()){
            String value0_float = ds.child("pickup").child("name").getValue(String.class);
            pickupName = String.valueOf(value0_float);
            
            mDistance.setText(pickupName);
        }
    }
    @Override
    public void onCancelled(DatabaseError databaseError) {
        throw databaseError.toException(); // never ignore errors    
    }
});

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • the mDistance is in an another class. – gunara Jun 29 '20 at 11:28
  • You'll have to make sure the `onDataChange` can reach that other class then. I hope my answer (and the link) makes it clear why that is needed: all code that needs the data, needs to be *inside* `onDataChange` or be called from there. – Frank van Puffelen Jun 29 '20 at 14:26