Last Updated: February 25, 2016
·
627
· rabidaudio

Making Android ArrayAdapters suck a little less

If you've ever worked with Android ListViews, you probably know it can be a bit of work just to make a list of objects.

Coming from Backbone.js, I really like the MVC model (where "C" is "Collection" here), so I want to map some set of objects (Collection of Models) to a ViewList.

I wrote a small class EasyArrayAdapter using generics which takes a lot of the boilerplate out. In the constructor, you give it the current Context, your layout resource ID, and your collection.

Then you just need to implement your ViewHolder (learn about the ViewHolder pattern here) and the mapping between your model and its view (onDrawView). It becomes even lighter if you're using ButterKnife.

Source (Gist)

Example

Model

class Car {
    String model;
    int year;

    public void start(){
        //start the car
    }

    ...
}

Layout

R.layout.car_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/model" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/year" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/startButton" />
</LinearLayout>

AdapterView

public class CarArrayAdapter extends EasyArrayAdapter<Car, CarArrayAdapter.ViewHolder> {
    public CarArrayAdapter(Context context, List<Car> collection){
        super(context, R.layout.car_item, collection);
    }

    @Override
    protected void onDrawView(final Controller c, ViewHolder h) {
        h.model.setText(c.getModel());
        h.year.setText(String.valueOf(c.getYear()));
        h.startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                c.start();
            }
        });
    }


    @Override
    protected ViewHolder createViewHolder(View v) {
        return new ViewHolder(v);
    }

    protected class ViewHolder {
        @InjectView(R.id.model) TextView model;
        @InjectView(R.id.year) TextView year;
        @InjectView(R.id.startButton) Switch startButton;
        public ViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }
}

In your Activity

carsListView.setAdapter(new CarsArrayAdapter(this, myCars));