# BaseAdapter with Android ListView
ListView is a ViewGroup that displays a list of vertically scrollable items. The list items are automatically inserted into the list using an `adapter` that is connected to a source, such as an array or a database query, and each item is converted into a row in the ListView.
## BaseAdapter
BaseAdapter, as it's name implies, is the base class for so many concrete adapter implementations on Android. It is abstract and therefore, cannot be directly instantiated.
## Using the BaseAdapter
To use the BaseAdapter with a ListView, a concrete implementation the `BaseAdepter` class that implements the following methods must be created:
* `int getCount()`
* `Object getItem(int position)`
* `long getItemId(int position)`
* `View getView(int position, View convertView, ViewGroup parent)`
Before we create our custom `BaseAdapter` implementation, we need to create the layout for the ListView row and also a model for the items in the ListView.
### Create model class
Each of our ListView rows will conatain an `Item name` and `Item description`, so our Model class is as follows:
**Item.java**
``` java
public class Item {
private String itemName;
private String itemDescription;
public Items(String name, String description) {
this.itemName = name;
this.itemDescription = description;
}
public String getItemName() {
return this.itemName;
}
public String getItemDescription() {
return itemDescription;
}
}
```
### ListView row layout
The xml file for the rows of the listview created in the `res/layout` folder is shown below: **layout_list_view_row_items.xml**
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text_view_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text_view_item_description"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
```
### Create the custom BaseAdapter implementation
``` java
public class CustomListAdapter extends BaseAdapter {
private Context context; //context
private ArrayList<Item> items; //data source of the list adapter
//public constructor
public CustomListAdapter(Context context, ArrayList<Item> items) {
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return items.size(); //returns total of items in the list
}
@Override
public Object getItem(int position) {
return items.get(position); //returns list item at the specified position
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//inflate the layout for each list row
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.layout_list_view_row_items, parent, false);
}
//get current item to be displayed
Item currentItem = (Item) getItem(position);
//get the TextView for item name and item description
TextView textViewItemName = (TextView) convertView.findViewById(R.id.text_view_item_name);
TextView textViewItemDescription = (TextView) convertView.findViewById(R.id.text_view_item_description);
//sets the text for item name and item description from the current item object
textViewItemName.setText(currentItem.getItemName());
textViewItemDescription.setText(currentItem.getItemDescription());
// returns the view for the current row
return convertView;
}
}
```
### Using the custom Adapter
The adapter can simply be used by instantiating it with the required paramters and set as the listview's adapter.
```java
//create the data source
ArrayList<Item> itemsArrayList = generateItemsList(); // calls function to get items list
//instantiate the custom list adapter
CustomListAdapter adapter = new CustomListAdapter(this, itemsArrayList);
//get the ListView and attach the adapter
ListView itemsListView = (ListView)findViewById(R.id.list_view_items);
itemsListView.setAdapter(adapter);
```
### ListView Optimization
To optimize the listview's performance, a new row layout should be inflated only when `convertView == null`. This is because the adapter's `getView` method is called whenever the listview needs to show a new row on the screen. The `convertview` gets recycled in this process. Hence, the row layout should be inflated just once when `convertview == null`, and it contents should be updated on subsequent `getView` calls, instead of inflating a new row on each call which is very expensive.
### Optimization using the ViewHolder pattern
One of the most common operation in Android is finding an inner view inside an inflated layout. This is usually done using the `findViewById` method. This operation is not trivial especially when the lisview has to frequently call `getView` when the list is scrolling.
The aim of the ViewHolder pattern, is to reduce the number of `findViewById` calls in the adapter's `getView`. A ViewHolder is practically a lightweight inner class that holds direct references to all inner views from a row. It is then stored as a **tag** in the row's view after inflating it. This way you’ll only have to use findViewById() when the layout is first created. Here’s a new implementation of our adapter's `getView` with View Holder pattern applied:
``` java
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.layout_list_view_row_items, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Item currentItem = (Item) getItem(position);
viewHolder.itemName.setText(currentItem.getItemName());
viewHolder.itemDescription.setText(currentItem.getItemDescription());
return convertView;
}
private class ViewHolder {
TextView itemName;
TextView itemDescription;
public ViewHolder(View view) {
itemName = (TextView)view.findViewById(R.id.text_view_item_name);
itemDescription = (TextView) view.findViewById(R.id.text_view_item_description);
}
}
```
The sample code for this tutorial can be found in this [github repo](https://github.com/mayojava/ListViewWithBaseAdapter).
## References
* [BaseAdapter Documentation](https://developer.android.com/reference/android/widget/BaseAdapter.html)
* [http://www.pcsalt.com/android/listview-using-baseadapter-android/](http://www.pcsalt.com/android/listview-using-baseadapter-android/)
* [http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/](http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/)