ListView using BaseAdapter – Android

Home / Android / ListView using BaseAdapter – Android

The previous post, Create List Using ListView was about displaying an array of a list. It dealt with only one element in a list item. In order to display a List with multiple views in a list item, BaseAdapter could be used. A ListView using BaseAdapter could display a List with multiple views in it.

In this tutorial, we are going to create ListView using BaseAdapter. So, this tutorial covers following points.
– Create custom BaseAdapter, and
– Inflating a custom view as the list item.

Before proceeding with this tutorial, we would like to share one piece of advice. If it is a problem only a ListView can solve, then only use ListView. Android has provided a new component RecyclerView. It is similar to ListView implementation. But, have many modifications for memory management. In addition to that, RecyclerView also provides animations for transitions like addition, removal and update of the list item. For its implementation, we have provided a tutorial RecyclerView – Android.

Create Android Application Project

If you are new to Android Studio, then you could learn about creating new projects from our tutorial Create Android Application Project in Android Studio Continued.

Create Android application project with following attributes.

Project Name CustomListViewDemo
Package Name pcsalt.example.customlistviewdemo
Minimum SDK Version 16
Activity Type Empty Activity
Activity Name MainActivity
Layout Name activity_name




Prepare layout screens

activity_main.xml: Layout for MainActivity.java. For this demo application, it would contain only a ListView.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/lvCustomList"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

layout_list_item.xml: Layout for list items to be displayed in ListView. In this list, each list item will display an ImageView and two TextView.

<?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:gravity="center_vertical"
    android:orientation="horizontal"
    android:padding="10dp">

    <ImageView
        android:id="@+id/ivIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/star1" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="Title" />

        <TextView
            android:id="@+id/tvDesc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="Description" />
    </LinearLayout>

</LinearLayout>

Create model class

ListData.java: This model class contains two String type values for Title and Description. imgResId is for displaying image in list items.

package pcsalt.example.customlistviewdemo;

/*
 * ListData class will hold data for displaying in ListView
 * */
public class ListData {

        String Description;
        String title;
        int imgResId;

        public String getDescription() {
                return Description;
        }

        public void setDescription(String description) {
                Description = description;
        }

        public String getTitle() {
                return title;
        }

        public void setTitle(String title) {
                this.title = title;
        }

        public int getImgResId() {
                return imgResId;
        }

        public void setImgResId(int imgResId) {
                this.imgResId = imgResId;
        }

}

Inherit BaseAdapter and modify according to functionality

MyBaseAdapter.java: Create a custom BaseAdapter to inflate the ListView items with layout_list_item.xml layout.

package pcsalt.example.customlistviewdemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

public class MyBaseAdapter extends BaseAdapter {

    ArrayList myList = new ArrayList();
    LayoutInflater inflater;
    Context context;


    public MyBaseAdapter(Context context, ArrayList myList) {
        this.myList = myList;
        this.context = context;
        inflater = LayoutInflater.from(this.context);
    }

    @Override
    public int getCount() {
        return myList.size();
    }

    @Override
    public ListData getItem(int position) {
        return myList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

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

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.layout_list_item, parent, false);
            mViewHolder = new MyViewHolder(convertView);
            convertView.setTag(mViewHolder);
        } else {
            mViewHolder = (MyViewHolder) convertView.getTag();
        }

        ListData currentListData = getItem(position);

        mViewHolder.tvTitle.setText(currentListData.getTitle());
        mViewHolder.tvDesc.setText(currentListData.getDescription());
        mViewHolder.ivIcon.setImageResource(currentListData.getImgResId());

        return convertView;
    }

    private class MyViewHolder {
        TextView tvTitle, tvDesc;
        ImageView ivIcon;

        public MyViewHolder(View item) {
            tvTitle = (TextView) item.findViewById(R.id.tvTitle);
            tvDesc = (TextView) item.findViewById(R.id.tvDesc);
            ivIcon = (ImageView) item.findViewById(R.id.ivIcon);
        }
    }
}

Let us discuss this block of code

if (convertView == null) {
    convertView = inflater.inflate(R.layout.layout_list_item, parent, false);
    mViewHolder = new MyViewHolder(convertView);
    convertView.setTag(mViewHolder);
} else {
    mViewHolder = (MyViewHolder) convertView.getTag();
}

In this code, we are checking if convertView is already initialized or not. If not, then inflate the list item layout, create ViewHolder object and save it in a tag of convertView. If convertView is already initialized, then retrieve the instance of ViewHolder from the convertView tag.

This is required to reuse the memory, which was already instantiated for previous list item. If this is not done, then for each new item getting displayed in the list will instantiate its own memory. And, it may cause OutOfMemoryException.

Populate BaseAdapter with data

To populate data into BaseAdapter, we will pass a List of model class from MainActivity.java

package pcsalt.example.customlistviewdemo;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.ListView;

import java.util.ArrayList;

public class MainActivity extends Activity {

    ListView lvDetail;
    Context context = MainActivity.this;
    ArrayList myList = new ArrayList();

    String[] title = new String[]{
            "Title 1", "Title 2", "Title 3", "Title 4",
            "Title 5", "Title 6", "Title 7", "Title 8"
    };
    String[] desc = new String[]{
            "Desc 1", "Desc 2", "Desc 3", "Desc 4",
            "Desc 5", "Desc 6", "Desc 7", "Desc 8"
    };
    int[] img = new int[]{
            R.drawable.star1, R.drawable.star2, R.drawable.star3, R.drawable.star4,
            R.drawable.star5, R.drawable.star6, R.drawable.star7, R.drawable.star8
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lvDetail = (ListView) findViewById(R.id.lvCustomList);
        // insert data into the list before setting the adapter
        // otherwise it will generate NullPointerException  - Obviously
        getDataInList();
        lvDetail.setAdapter(new MyBaseAdapter(context, myList));
    }

    private void getDataInList() {
        for (int i = 0; i < title.length; i++) {
            // Create a new object for each list item
            ListData ld = new ListData();
            ld.setTitle(title[i]);
            ld.setDescription(desc[i]);
            ld.setImgResId(img[i]);
            // Add this object into the ArrayList myList
            myList.add(ld);
        }
    }

}

Download Source:

Download source code from GitHub

Video tutorial: