Kevin Vugts Kevin Vugts - 1 month ago 8
Android Question

Append object to ArrayList

Currently I am trying to add data that comes from firebase to an arrayList I have made in my activity. When I use hardcoded data it works but when I use a for loop to get values from the firebase db it doesn't work anymore. It doesn't append it.

Here is my code:

package com.example.fhict.hellogridview.activities;

import android.content.Intent;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.fhict.hellogridview.Model.Student;
import com.example.fhict.hellogridview.R;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;

import static com.example.fhict.hellogridview.R.drawable.profile;
import static com.example.fhict.hellogridview.R.drawable.car;

public class class_overview extends AppCompatActivity {

public final static String EXTRA_MESSAGE = "com.example.fhict.hellogridview";
private List<Student> myStudents = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_class_overview );

ValueEventListener usersListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {

for (DataSnapshot mydata : dataSnapshot.getChildren()){
System.out.println(mydata.getValue());
System.out.println(mydata.child("profile").child("username").getValue());

String name = (String) mydata.child("profile").child("username").getValue();

myStudents.add(new Student(name, 500, profile, "Group 2"));

myStudents.add(new Student());
}
}

@Override
public void onCancelled(DatabaseError databaseError) {

}
};

FirebaseDatabase.getInstance().getReference().child("users").addValueEventListener(usersListener);

// populateCarList();
populateListView();
System.out.println(myStudents);
}


// private void populateCarList() {
// myStudents.add(new Student("Farshad", 1430, profile, "Groep 1"));
// myStudents.add(new Student("Kevin", 1442, profile, "Groep 1"));
// myStudents.add(new Student("Tawab", 1528, profile, "Groep 1"));
// myStudents.add(new Student("Melvin", 2005, profile, "Groep 1"));
// myStudents.add(new Student("Theo", 1940, profile, "Groep 2"));
// myStudents.add(new Student("Stefan", 2005, profile, "Groep 2"));
// myStudents.add(new Student("Ronald", 1999, profile, "Groep 2"));
// myStudents.add(new Student("Kees", 2005, profile, "Groep 2"));
// myStudents.add(new Student("Kevin", 1940, profile, "Groep 3"));
// myStudents.add(new Student("Joey", 2005, profile, "Groep 3"));
// myStudents.add(new Student("Herm", 1999, profile, "Groep 3"));
// myStudents.add(new Student("Peter", 2005, profile, "Groep 3"));
// }

private void populateListView() {
ArrayAdapter<Student> adapter = new MyListAdapter();
ListView list = (ListView) findViewById(R.id.carsListView);
list.setAdapter(adapter);
}

public class MyListAdapter extends ArrayAdapter<Student> {
public MyListAdapter () {
super(class_overview.this, R.layout.item_view, myStudents);
}

@Override
public View getView(int position, final View convertView, ViewGroup parent) {
// Dit creeërt de view
View itemView = convertView;

if(itemView == null) {
itemView = getLayoutInflater().inflate(R.layout.item_view, parent, false);
}

itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

// Maakt de Toast
TextView hallo = (TextView) v.findViewById(R.id.item_txtMake);
Toast.makeText(v.getContext(),"Hallo " + hallo.getText() ,Toast.LENGTH_LONG).show();

// Zet de naam in Extra
Intent intent = new Intent(getContext(), Profile.class);
TextView makeText = (TextView) v.findViewById(R.id.item_txtMake);
intent.putExtra(EXTRA_MESSAGE, makeText.getText());
startActivity(intent);

// Zet de profilepic in Extra
//intent.putExtra("imageIds", currentCar.getIconID());
//startActivity(intent);
}
});

// Vindt de auto
Student currentCar = myStudents.get(position);

// Vult de view
ImageView imageView = (ImageView)itemView.findViewById(R.id.item_icon);
imageView.setImageResource(currentCar.getIconID());

// Automerk
TextView makeText = (TextView) itemView.findViewById(R.id.item_txtMake);
makeText.setText(currentCar.getMake());

// Jaar
TextView yearText = (TextView) itemView.findViewById(R.id.item_txtYear);
yearText.setText("" + currentCar.getYear());

// Conditie
TextView conditionText = (TextView) itemView.findViewById(R.id.item_txtCondition);
conditionText.setText(currentCar.getCondition());

return itemView;

}
}
}


Does anybody have a clue why the array is still empty?

Answer

You need to understand the flow of async code.

The initial for-loop you had was inserting data into the list before you refreshed the View.

With Firebase, that method happens in the background. The ValueListener won't get "triggered" until the network request finishes.

Simply move populateListView() to after that for loop.

private List<Student> myStudents = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_class_overview );

    ValueEventListener usersListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            Integer index = 1; // Moved outside the loop
            myStudents.clear(); // Remove existing data
            for (DataSnapshot mydata : dataSnapshot.getChildren()){

                String name = (String) mydata.child("profile").child("username").getValue();

                myStudents.add(new Student(name, index+1, profile, "Group 2"));
            }

            // Update the UI with the students from this callback
            populateListView();
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };

    // Asynchronous! Happens in the background
    FirebaseDatabase.getInstance().getReference().child("users").addValueEventListener(usersListener);

   // Code here continues in the current, main UI thread. 

}

Alternatively, use adapter.add rather than directly adding to the ArrayList and needing to refresh the UI yourself.

private ArrayAdapter<Student> adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_class_overview );

    adapter = new MyListAdapter();
    ListView list = (ListView) findViewById(R.id.carsListView);
    list.setAdapter(adapter);

    ValueEventListener usersListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            Integer index = 1; // Moved outside the loop
            adapter.clear(); // Remove existing data
            for (DataSnapshot mydata : dataSnapshot.getChildren()){

                String name = (String) mydata.child("profile").child("username").getValue();

                // Update the UI with the students from this callback
                adapter.add(new Student(name, index+1, profile, "Group 2"));
            }



        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };


    // Asynchronous! Happens in the background
    FirebaseDatabase.getInstance().getReference().child("users").addValueEventListener(usersListener);

   // Code here continues in the current, main UI thread. 

}
Comments