Adapter / ArrayAdapter / SimpleAdapter

Adapters – Part 2

In the previous article we began our look at Adapters by connecting up the List Navigation Spinner in our ActionBar. In this article we’ll look at applying an Adapter to a ListView.

Previously we created a fragment named ListViewFragment which is currently empty, save for inflating a simple layout containing a single ListView. To populate this ListView we use an Adapter. Let’s start by doing something really simple, and very similar to how we connected up our List Navigation Spinner: Use an ArrayAdapter:

public class ListViewFragment extends ListFragment
{
	private static final String[] items = new String[] {
		"One", "Two", "Three", "Four", "Five"
	};
	
	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container, Bundle savedInstanceState)
	{
		return inflater.inflate(R.layout.listview, 
			container, false);
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		ListAdapter adapter = new ArrayAdapter(
			getActivity(), 
			android.R.layout.simple_list_item_1, items);
		setListAdapter(adapter);
	}
}

We’ve used a static String array, and a different layout, but essentially this is exactly the same as we did with the Navigation Spinner. This demonstrates how the Adapter is completely decoupled from the control that it is binds to. ArrayAdapter extends BaseAdapter which implements both ListAdapter and SpinnerAdapter interfaces which means that it can be used to populate either of these controls.

This gives us the following:

ArrayAdapterString

So what if we want to do something slightly more complex. If we want to use android.R.layout.simple_list_item_2 instead of the previous layout, it includes two TextView objects which we need to bind to. Using the ArrayAdapter as before will not work because we now have to bind two controls, so we’ll use a SimpleAdapter instead:

public class SimpleAdapterFragment extends ListFragment
{
	private static final List> items = 
		new ArrayList>();
	private static final String[] keys = 
		{ "line1", "line2" };
	private static final int[] controlIds = 
		{ android.R.id.text1, 
		android.R.id.text2 };
	
	static
	{
		Map map = 
			new HashMap();
		map.put("line1", "Title One");
		map.put("line2", "Subtitle One");
		items.add(map);
		map = new HashMap();
		map.put("line1", "Title Two");
		map.put("line2", "Subtitle Two");
		items.add(map);
		map = new HashMap();
		map.put("line1", "Title Three");
		map.put("line2", "Subtitle Three");
		items.add(map);
		map = new HashMap();
		map.put("line1", "Title Four");
		map.put("line2", "Subtitle Four");
		items.add(map);
		map = new HashMap();
		map.put("line1", "Title Five");
		map.put("line2", "Subtitle Five");
		items.add(map);
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, 
		ViewGroup container, 
		Bundle savedInstanceState)
	{
		return inflater.inflate(R.layout.listview, 
			container, false);
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState)
	{
		super.onActivityCreated(savedInstanceState);
		ListAdapter adapter = new SimpleAdapter(
			getActivity(), 
			items, 
			android.R.layout.simple_list_item_2, 
			keys, 
			controlIds );
		setListAdapter(adapter);
	}
}

Despite it’s name, SimpleAdapter is actually a little more complex than the very basic ArrayAdapter implementation that we used before. However, it is actually a pretty simple way of binding multiple controls within each item in our ListView.

It works by storing the data that we want to bind to the control within a List of Maps. Each item in the List represents a single item in the ListView, and the Map contains the values which get assigned to the different controls. The two TextViews in the layout have ids of android.R.id.text1 and android.R.id.text2 and we need to map these values to the controls. This is done using two arrays, keys contains a list of keys used in the Map, and controlIds contains a list of control ids. SimpleAdapter will bind the controls to their respective Map values:

controlId[i].setText(map.get(keys[i]));

This gives us the following:

SimpleAdapter

So we’ve seen how we can use ArrayAdapter to perform the simplest of bindings, and then SimpleAdapter to perform something very slightly more complex. Actually we can also use ArrayAdapter to perform this second kind of binding, but there are some optimisations that we need to be aware of before we do so. In the next article we’ll look at this.

The source code for this article is available here.

© 2013 – 2014, Mark Allison. All rights reserved.

Copyright © 2013 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.