Search code examples
javaandroidperformanceandroid-arrayadapterandroid-adapter

How to fill a Spinner from my code in Java (Android Studio)


I'm making an example with Android Studio and I want to add items to a List that is displayed in a Spinner. Looking here, I found this answer that helped me a lot.

Basically I create an ArrayAdapter and assign it to my Spinner with the modified list every time I press a button. I was wondering if there is a more efficient way of doing this.

I have an EditText where I write a string and when I press the button I add it to an ArrayList and use it to fill the Spinner.

This is the code of my MainActivity (btnAgregar_Click is the method executed when you press the button):

public class MainActivity extends AppCompatActivity {

    private final List<String> lista = new ArrayList<>();

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

    public void btnAgregar_Click(View v) {
        // Create Java objects that refer to XML interface
        EditText txtArticulo = findViewById(R.id.txtArticulo);
        Spinner spinLista = findViewById(R.id.spinLista);

        // Read text in txtArticulo
        String articulo = txtArticulo.getText().toString();

        // If there is text, add it to the list
        if (articulo.length() > 0) {
            lista.add(articulo);
            txtArticulo.setText("");
        } else {
            // Otherwise, show an error
            Toast.makeText(this,"Error: escribe un artículo",Toast.LENGTH_SHORT).show();
        }

        // Add adapter to the Spinner
        ArrayAdapter<String> adapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_item, lista);

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinLista.setAdapter(adapter);
    }
}

Although it works, I think it's an overkill to create an ArrayAdapter, initialize it and add it to the Spinner every single time I press the button. Is this the best way to do it? Can I just create the adapter once and just change something when I add an item to the ArrayList?


Solution

  • You are right about creating new instance of ArrayAdapter every time you want to insert a new item. ArrayAdapter has a method add(@Nullable T object) which can be useful in your case. What it does under the hood - it just add new item to internal array and calls notifyDataSetChanged() to let adapter redraw its contents.

    So I would rewrite your code as follows:

    ArrayAdapter<String> adapter;
    
    public void btnAgregar_Click(View v) {
            // Create Java objects that refer to XML interface
            EditText txtArticulo = findViewById(R.id.txtArticulo);
            Spinner spinLista = findViewById(R.id.spinLista);
    
            // Read text in txtArticulo
            String articulo = txtArticulo.getText().toString();
    
            if (!articulo.isEmpty()) {
                if (adapter != null) {
                    adapter.add(articulo);
                } else {
                    adapter = new ArrayAdapter<>(
                            this, android.R.layout.simple_spinner_item, new ArrayList<String>(){{add(articulo);}});
                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    spinLista.setAdapter(adapter);
                }
                txtArticulo.setText("");
            } else {
                Toast.makeText(this, "Error: escribe un artículo", Toast.LENGTH_SHORT).show();
            }
        }
    

    As you can see there is no need to manually add item to lista ArrayList. Also it is good practice to let Adapter manage its contents - that is what we do by calling add() method instead of manual modification of lista array. So there will be no hard connections and your code will be more maintainable.