Dynamically add items to list view using custom adapter for Android app

38,619

Solution 1

  1. In your adapter change the Locations data[] from array to ArrayList<Location> and override the appropriate constructor
  2. In your activity, make your variable data a field (type ArrayList<Location>)
  3. When you add a location you can use data.add(location)
  4. Then you can call notifyDatasetChanged() on your adapter

Example code.

Solution 2

Store your data in an ArrayList<Location> instead of just Location[], and then make a public class in your list adapter:

ArrayList<Location> data = new ArrayList<Location>();

@Override
public void add(Location location) {
    data.add(location);
    notifyDataSetChanged();
}

Then, when you want to add an item to the list, just call location_data.add(new_location).

Edit: It looks like you have your pick from several mostly identical answers.

Solution 3

Looks like you need to override the add method in your LocationAdapter class to add the object to the internal list

@Override
public void add(Location location)
{
    super.add(location);
    data.add(location);
}

This implementation requires that you change data to an ArrayList instead of just an array, otherwise you would have to code the array re-sizing yourself.

ArrayList<Location> data = null; // Alternatively use new ArrayList<Location>();

If you don't do this, the internal data will remain unchanged and a call to add will do not change the list. This is bad because you use the data variable to get the values for the views.

Solution 4

In your main activity, I'd recommend using an ArrayList< Location > rather than Location[] to make it easier to add new Location elements. Then, rather than having LocationAdapter extend ArrayAdapter< Location >, have it extend ListAdapter< Location > so you can pass your ArrayList< Location > to it.

That said, all you need to do in your addLocation(Location l) method in your MainActivity, is add an element to either the Location[] or ArrayList< Location > data structure you passed to your adapter, and then call:

adapter.notifyDataSetChanged();

Note that you'll need to make your adapter a member variable in your MainActivity to allow access outside of your onCreate().

Share:
38,619
user1282637
Author by

user1282637

Updated on July 28, 2022

Comments

  • user1282637
    user1282637 almost 2 years

    So, right now I have a custom adapter class that takes in an array of Locations and adds them to a ListView. This is all fine and dandy, but I would like to add Locations to this listview after this initialization. For example, someone can "add a Location" and it will add it to this ListView. Here is my Main Activity:

    package com.example.listviewtest;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ListView;
    
    public class MainActivity extends Activity {
    
    private ListView listView1;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        Location location_data[] = new Location[]
        {
            new Location(R.drawable.ic_launcher, "Location 1", "Fruit!", "2 miles", "8-4 mon-fri\nclosed sun"),
            new Location(R.drawable.ic_launcher, "Location 2", "Veggies!", "2 miles", "8-5"),
            new Location(R.drawable.ic_launcher, "Location 3", "Plants!", "2 miles", "8-5"),
            new Location(R.drawable.ic_launcher, "Location 4", "Flowers!", "2 miles", "8-5"),
            new Location(R.drawable.ic_launcher, "Location 5", "Baked Goods!", "2 miles", "8-5")
        };
    
       LocationAdapter adapter = new LocationAdapter(this, 
                R.layout.listview_item_row, location_data);
    
       //adapter.add(new Location(R.drawable.ic_launcher, "Location 6", "Veggies!", "2 miles", "8-5"));
    
    
        listView1 = (ListView)findViewById(R.id.listView1);
    
        View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
        listView1.addHeaderView(header);
    
        listView1.setAdapter(adapter);
    }
    }
    

    This works. I want to now do something like adapter.add(new Location(R.drawable.ic_launcher, "Location 6", "Veggies!", "2 miles", "8-5")); AFTER filling it with the array.

    Here is my LocationAdapter class:

    package com.example.listviewtest;
    
    import android.app.Activity;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class LocationAdapter extends ArrayAdapter<Location>{
    
    Context context; 
    int layoutResourceId;    
    Location data[] = null;
    
    public LocationAdapter(Context context, int layoutResourceId, Location[] data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        LocationHolder holder = null;
    
        if(row == null)
        {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
    
            holder = new LocationHolder();
            holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
            holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
            holder.details = (TextView)row.findViewById(R.id.details);
            holder.distance = (TextView)row.findViewById(R.id.distance);
            holder.hours = (TextView)row.findViewById(R.id.hours);
    
            row.setTag(holder);
        }
        else
        {
            holder = (LocationHolder)row.getTag();
        }
    
        Location location = data[position];
        holder.txtTitle.setText(location.title);
        holder.imgIcon.setImageResource(location.icon);
        holder.details.setText(location.details);
        holder.distance.setText(location.distance);
        holder.hours.setText(location.hours);
    
        return row;
    }
    
    static class LocationHolder
    {
        ImageView imgIcon;
        TextView txtTitle;
        TextView details;
        TextView distance;
        TextView hours;
    }
    }
    

    Any ideas on how I can implement this? Thanks.

  • sotrh
    sotrh almost 10 years
    You won't have to use the adapter.notifyDataSetChanged() because you are adding values in onCreate (aka. the view isn't showing yet). If you do it elsewhere you will.
  • user1282637
    user1282637 almost 10 years
    Thank you, this is what I had to do
  • zionpi
    zionpi about 8 years
    if data element inside Location data array facility with media info which comes from internet,call notifyDatasetChanged()every time will make the app ANR.