1

I have an object:

private ArrayList<HashMap<String, String>> customerDataList;

Which I populate with data retrieved from a web service call. The below is inside a loop iterating over the retrieved json data:

HashMap<String, String> customer = new HashMap<>();
//snip
customer.put("CustomerName", customerName);
//snip
customerDataList.add(customer);
//rinse and repeat

Then I display this in a list view in my activity with:

ListAdapter adapter = new SimpleAdapter(Activity.this, customerDataList,
                R.layout.list_item, new String[] {"CustomerName"}, new int[] { R.id.customerName });
setListAdapter(adapter);

However I am wondering if there is a way I can use a List instead.

I created my customer class, created a List of it like so:

private List<Customer> customerList;

However when it comes to setting the ListAdapter I am unsure of what to put. I replaced customerDataList with customerList but I receive errors.

Edit: The error is

SimpleAdapter() in SimpleAdapter cannot be applied to:
Expected data: java.util.Map<java.lang.String.?>>
Actual arguments: customerList <Customer>

Edit: my class structure

private class Customer
{
    private int customerID;
    private String customerName;
    private String customerLocation;
    private String runningTime;
    private double distance;
}
2
  • What error? Can you post error or stack trace Commented Jan 10, 2015 at 19:09
  • Have you tried creating a custom adapter? Commented Jan 10, 2015 at 19:16

3 Answers 3

1

If you want a use a list of custom objects you need to use another adapter e.g. ArrayAdapter:

List<Customer> customerList = null;
ArrayAdapter<Customer> customerAdapter = new ArrayAdapter<Customer>(this,
        R.layout.list_item, customerList);

Now since ArrayAdapter expects strings to come out of your custom objects, override a toString method in your class:

class Customer {
    String customerName;

    @Override
    public String toString() {
        return customerName;
    }
}

If your customer class has multiple fields that will need to be used in your adapter, you will need a custom adapter, something like this:

// Turns out that when the layout is not a TextView, you need to provide the id
// of the TextView the adapter can bind to
ArrayAdapter<Customer> customerAdapter = new ArrayAdapter<Customer>(this,
        R.layout.list_item, R.id.customer_name, customerList) {
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);

        TextView name = view.findViewById(R.id.customer_name);
        TextView surname = view.findViewById(R.id.customer_surname);

        name.setText(getItem(position).customerName);
        surname.setText(getItem(position).customerSurname);

        return view;
    }
};

You can google to find some performance adjustments for custom adapters.

Sign up to request clarification or add additional context in comments.

6 Comments

The View view = super.getView(...) generates an error when I run. /ArrayAdapter﹕ You must supply a resource ID for a TextView
@andrewb I updated my answer. However you should have provided important details (like your customer class structure and the fields that the adapter will use) in your question.
Thanks for your help. So how do I add more fields, such as R.id.customer_name, R.id.customerAddress? I added customer address and it complains about the constructor
@andrewb to add more fields, modify the getView method, not the constructor. In my example there are 2 fields, you can add as many as you like as long as they're found in the list_item.xml and exist in your Customer class.
Thanks, so that works, but I do not understand why R.id.customer_name is in the ArrayAdapter constructor but not the other fields? For example if I bound 5 fields that is the only field in ctor
|
0

You can use

List<Customer>

but you need to go for a custom adapter instead of Simple adapter.

The data containing the customer object need to be set, the simple adapter can only accept the name value pare map. So you need to extend the adapter/Basadpter class the requirement.

1 Comment

And how does one do that?
0

The easiest way is to assign the values from Customer object to views in your list row layout is to create a custom Adapter extending the ArrayAdapter class:

public class CustomAdapter extends ArrayAdapter<Customer> {

private final Context context;
  private final Customer[] values;

  public MySimpleArrayAdapter(Context context, Customer[] values) {
    super(context, R.layout.rowlayout, values);
    this.context = context;
    this.values = values;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {

    if(convertView == null {
       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       convertView = inflater.inflate(R.layout.listviewrowlayout, parent, false);
    }

    TextView customerName= (TextView) convertView.findViewById(R.id.customerName);
    TextView customerAge= (TextView) convertView.findViewById(R.id.customerAge);

    customerName.setText(values[position].getName());
    customerAge.setText(values[position].getAge());

    return convertView;
  }
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.