Android – ListView – 5 – Optimized custom ListView

By -

I had written article Android – ListView – 4 – Custom ListView, in this article we are passing detail arrays to the listview custom adapter. But what if we are having list of objects and want to pass to the custom adapter class to prepare ListView? So this is the purpose of this article.

FYR, Related Articles are:

  1. Android – ListView – 1 – Simple
  2. Android – ListView – 2 – Custom ListView with Two TextViews
  3. Android – ListView – 3 – Custom ListView
  4. Android – ListView – 4 – Custom ListView
Now, let me post here the solution of the above problem:
This article is having the optimized solution for the above 4th article. For the same, i had created ArrayList<Object> with list of objects so we need to manage the horrible arrays and ArrayList is easy to handle as we can add/delete/get objects easily.

Custom ListView Android

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

    <ListView
        android:id="@+id/listView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </ListView>

</LinearLayout>
items.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
	android:id="@+id/relativeLayout1"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:padding="5dip">

    <ImageView
    	android:layout_width="50dip"
    	android:layout_height="50dip"
    	android:id="@+id/imgViewLogo"
    	android:src="@drawable/icon"
    	android:layout_alignParentLeft="true"
    	android:layout_centerInParent="true"
    	android:scaleType="center">
    </ImageView>

    <TextView
    	android:textAppearance="?android:attr/textAppearanceLarge"
    	android:layout_height="wrap_content"
    	android:text="TextView"
    	android:layout_width="wrap_content"
    	android:id="@+id/txtViewTitle"
    	android:layout_toRightOf="@+id/imgViewLogo"
    	android:layout_marginLeft="2dip">
    </TextView>

    <TextView
    	android:layout_height="wrap_content"
    	android:text="TextView"
    	android:layout_width="wrap_content"
    	android:id="@+id/txtViewDescription"
    	android:layout_toRightOf="@+id/imgViewLogo"
    	android:layout_below="@+id/txtViewTitle"
    	android:layout_marginLeft="2dip">
    </TextView>

</RelativeLayout>
ItemBean.java

package com.technotalkative.listview5;

public class ItemBean
{
	String title;
	String description;
	int image;

	public String getTitle() {
		return title;
	}

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

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public int getImage() {
		return image;
	}

	public void setImage(int image) {
		this.image = image;
	}
}
ListViewCustomAdapter.java
package com.technotalkative.listview5;

import java.util.ArrayList;

import android.app.Activity;
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;

public class ListViewCustomAdapter extends BaseAdapter{

	ArrayList&lt;Object&gt; itemList;

    public Activity context;
    public LayoutInflater inflater;

    public ListViewCustomAdapter(Activity context,ArrayList&lt;Object&gt; itemList) {
        super();

        this.context = context;
        this.itemList = itemList;

        this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return itemList.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return itemList.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    public static class ViewHolder
    {
        ImageView imgViewLogo;
        TextView txtViewTitle;
        TextView txtViewDescription;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub

        ViewHolder holder;
        if(convertView==null)
        {
            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.items, null);

            holder.imgViewLogo = (ImageView) convertView.findViewById(R.id.imgViewLogo);
            holder.txtViewTitle = (TextView) convertView.findViewById(R.id.txtViewTitle);
            holder.txtViewDescription = (TextView) convertView.findViewById(R.id.txtViewDescription);

            convertView.setTag(holder);
        }
        else
            holder=(ViewHolder)convertView.getTag();

        ItemBean bean = (ItemBean) itemList.get(position);

        holder.imgViewLogo.setImageResource(bean.getImage());
        holder.txtViewTitle.setText(bean.getTitle());
        holder.txtViewDescription.setText(bean.getDescription());

        return convertView;
    }

}
MainActivity.java
package com.technotalkative.listview5;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class MainActivity extends Activity implements OnItemClickListener {

    ListView lview3;
    ListViewCustomAdapter adapter;
    private ArrayList&lt;Object&gt; itemList;
    private ItemBean bean;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        prepareArrayLits();
        lview3 = (ListView) findViewById(R.id.listView1);
        adapter = new ListViewCustomAdapter(this, itemList);
        lview3.setAdapter(adapter);

        lview3.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(AdapterView&lt;?&gt; arg0, View arg1, int position, long id) {
        // TODO Auto-generated method stub
    	ItemBean bean = (ItemBean) adapter.getItem(position);
    	Toast.makeText(this, "Title =&gt; "+bean.getTitle()+" n Description =&gt; "+bean.getDescription(), Toast.LENGTH_SHORT).show();
    }

    /* Method used to prepare the ArrayList,
     * Same way, you can also do looping and adding object into the ArrayList.
     */
    public void prepareArrayLits()
    {
    	itemList = new ArrayList&lt;Object&gt;();

    	AddObjectToList(R.drawable.ic_add, "Add", "Add desc");
    	AddObjectToList(R.drawable.ic_delete, "Delete", "Delete desc");
    	AddObjectToList(R.drawable.ic_down, "Down", "Down desc");
    	AddObjectToList(R.drawable.ic_info, "Information", "Information desc");
    	AddObjectToList(R.drawable.ic_help, "Help", "Help desc");
    	AddObjectToList(R.drawable.ic_download, "Download", "Download desc");
    	AddObjectToList(R.drawable.ic_mail, "Mail", "Mail desc");
    	AddObjectToList(R.drawable.ic_search, "Search", "Search desc");
    	AddObjectToList(R.drawable.ic_settings, "Settings", "Settings desc");
    }

    // Add one item into the Array List
    public void AddObjectToList(int image, String title, String desc)
    {
    	bean = new ItemBean();
    	bean.setDescription(desc);
    	bean.setImage(image);
    	bean.setTitle(title);
    	itemList.add(bean);
    }
}

You can download source code from here: Android Custom ListView.

Paresh Mayani

Paresh Mayani is a lead android developer from India. Currently, He is Sr. Software engineer at InfoStretch Solutions Pvt. Ltd. He has been developing android apps since very 1st version i.e. Android 1.5, he says he has seen days and nights of Android history. He is the Head/Organizer of Google Developers Group (GDG), Ahmedabad

  • http://en.gravatar.com/chiataytuday chiataytuday

    Thanks a lot.

    That’s what I’m very need.

    if i have issue. i will comment in blog.

    Thanks,
    Hieu

  • http://en.gravatar.com/chiataytuday chiataytuday

    I have done. For example, very useful.
    But next I have a problem when retrieving data in the program crash. I want to download the image to save to cache. after i view to listview.

    thanks,
    Hieu

  • alex

    Hello good work but i think you should have use the HashMap instruction
    like this maybe i’m wrong but it is more easy

    import java.util.HashMap;

    ArrayList<HashMap> listItem = new ArrayList<HashMap>();

    HashMap map;
    map = new HashMap();
    map.put(“title”, “Add”);
    map.put(“description”, “Add desc”);
    map.put(“img”, String.valueOf(R.drawable.myimage));
    listItem.add(map);

    • http://pareshnmayani.wordpress.com Paresh N Mayani

      Hello Alex,
      Its also a way to implement the same functionality. As per your comment, we can say we need not to create “ItemBean” class, instead we have to deal with HashMap only.

      Anyway, Thanx for the feedback :)

  • kumar

    HI can u please tell me how to move the coin or image at android gridview

    • http://pareshnmayani.wordpress.com Paresh N Mayani

      Dear this is the off topic on this article as this is regarding the GridView. Anyway, what you are trying to implement, i didn’t get your problem exactly ? Why do you want to move the coin or image inside the gridview?

  • http://www.otssolutions.com/android-software-development.html Android Developers

    your articles are alwaz very informative

    Thanks a lot for all the info u provided.. n waiting for more post from your side

  • Jan

    Thanks for the sample code. I wanted to customize each line of the list view (ie. hide buttons, show icons, change font). It took me a while to figure out that android is reusing the views after they rotate out of the screen. All I really needed was to ignore the “if(convertView==null)” condition to prevent the reuse. Now each of the lines can have a custom look.

    • http://pareshnmayani.wordpress.com Paresh N Mayani

      Thanx for the informative and descriptive feedback.

  • selva

    I’m developing android application . In that I have to maintain huge image in online database . So I have to send image to server and fetch image from server frequently . And also I have to show that image in list view . So while downloading from server takes average 50 seconds per image in data plan not in wifi . I am using sync adapter method to download the image . So is there any way to minimize the download time . For example I am having 200 image , so that it takes minimum 1 hour to download and show it in application . Is any way to easy this work … Thanks in Advance …….

    • http://www.technotalkative.com/ Paresh N. Mayani

      Hello Selva,
      I am not agree with the solution that you are implementing right now because its obvious that its takes time to download images and display those inside the ListView.

      Instead, the solution which i can suggest you is to “Lazy Loading images in ListView asynchronously”, this approach don’t wait for all the images to download, instead it display image in ImageView or in ListView as and when they synced so our UI is not going to freeze anymore, now for this approach i would suggest you to look into the below solutions:

      1. Android – Universal Image Loader by Nostra
      2. Lazy Load of images in ListView by Fedor.

      FYI, these both solutions are caching images in your external storage.

      Let me know!!

  • Laces

    Thanks for the great tutorial!

    There is one thing what i can’t understand.

    In the Adapter class at this line :

    convertView = inflater.inflate(R.layout.items, null);

    previously you didn’t created any file witch name is items.
    In your listview tutorials i saw at this part you used the listview_row.xml
    But if i use the same here i got a runtime error

    Could you help me?

    • http://www.technotalkative.com/ Paresh N. Mayani

      Hello Laces,
      FYI, i have used inflate function of LayoutInflater to instantiates a layout file into its corresponding View Object. Here View is every items of ListView.

      For more info, check this: LayoutInflater

  • http://PeakMobileDesigns.com Andrew

    Hi. This custom list view is exactly what I am trying to build. But I am trying to get each item in the list to open a new activity. Also, I have this list view inside a tab bar layout. So when the user clicks an item in the list, it should open a new activity that is on a stack and the parent tab bars are still visible. Any suggestions?

    Thanks!

    • http://www.technotalkative.com/ Paresh N. Mayani

      Hello Andrew,
      Here are the suggestions to your problem.

      1. But I am trying to get each item in the list to open a new activity.
      => Inside onItemClick method, we can have a particular object from the clicked position by using:

      ItemBean bean = (ItemBean) adapter.getItem(position);

      Now to pass this object to another activity, check this tutorial: http://www.technotalkative.com/android-send-object-from-one-activity-to-another-activity/

      2. Also, I have this list view inside a tab bar layout. So when the user clicks an item in the list, it should open a new activity that is on a stack and the parent tab bars are still visible.
      => You can either implement Fragments or ActivityGroup. FYI, ActivityGroup is deprecated now but you can still use it if you want.