SyntaxHighlighter

Sunday, November 27, 2011

How To work With Android ListView

A ListView is the most common in Android platform.We use ListView in lot of cases.People use ListView with different way.But ListView is very complex and very resource hungry widget.If we don’t use ListView properly it will cause to lot of problems.So here I follow the best way to implement ListView.Basically I defined my own layout for ListView item and then bind it to custom object(Employer) and show all the objects in ListView.
listDisplaying string or any other primitive data type in list view is very easy.here I show your little bit advance, performance optimized ListView and use best practices to implement that.
When talking about ListView implementation we have to consider mainly three things ListView,ListActivity and Adapters.
1)ListView is use to show scrollable items in mobile screen.
2)ListActivity is extended Activity with predefined method for specially handling ListView
3) Adapters act as bridge between view and data.This provides data to view and also adapters make view for each item in data set like List(in my case List<Employer>).
Lets see how to implement those things
  1. First we have to create Android project in Eclipse and set it main layout to ListView. The following code shows you main.xml layout file.
    <?xml version="1.0" encoding="utf-8"?>
    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
    </ListView>
    here you should define android:id as list because we going to use ListActivity.
  2. Then we want another layout for ListView item.So add layout file called employer_list_item.xml. then add following code.
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/employee"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal" android:layout_gravity="fill_vertical">
        <ImageView
            android:id="@+id/imageViewEmployer"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="5dp"
            android:src="@drawable/ic_launcher" />
        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:orientation="vertical" android:padding="5dp">
            <TextView
                android:id="@+id/textViewName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Medium Text"
                android:textAppearance="?android:attr/textAppearanceMedium" android:gravity="center"/>
            <TextView
                android:id="@+id/textViewAddress"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Small Text"
                android:textAppearance="?android:attr/textAppearanceSmall"/>
        </LinearLayout>
    </LinearLayout>
  3. Then we want create Adapter for our ListView. Here I use ArrayAdapter as our Adapter.In this example I create Employer object list and set name,address and image according to their role that mean admin or user.first define Employer.java class as following.
    public class Employer {
     private String name;
     private String address;
     private boolean isAdmin=false; 
     public Employer()
     {  
     } 
     public Employer(String name,String address,boolean isAdmin ) {
      this.name=name;
      this.address=address;
      this.setAdmin(isAdmin);
     } 
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     public String getAddress() {
      return address;
     }
     public void setAddress(String address) {
      this.address = address;
     }
     public boolean isAdmin() {
      return isAdmin;
     }
     public void setAdmin(boolean isAdmin) {
      this.isAdmin = isAdmin;
     }
    }
      After that we are going to define our ArrayAdapter.So add java class called EmployerArrayAdapter.java extending ArrayAdapter with Employer type as following.
    import java.util.List;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class EmployerArrayAdapter extends ArrayAdapter<Employer> {
     
     private LayoutInflater inflater;
     private List<Employer> data;
     
     public EmployerArrayAdapter(Context context,List<Employer> objects) {
      super(context, R.layout.employer_list_item, objects);
      
      inflater= LayoutInflater.from(context);
      this.data=objects;
     }
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
      ViewHolder holder;
      //if it's not create convertView yet create new one and consume it
      if(convertView == null){
       //instantiate convertView using our employee_list_item
       convertView = inflater.inflate(R.layout.employer_list_item, null);
       //get new ViewHolder
       holder =new ViewHolder();
       //get all item in ListView item to corresponding fields in our ViewHolder class
       holder.image=(ImageView) convertView.findViewById(R.id.imageViewEmployer);
       holder.name =(TextView) convertView.findViewById(R.id.textViewName);
       holder.address =(TextView) convertView.findViewById(R.id.textViewAddress);
       //set tag of convertView to the holder
       convertView.setTag(holder);
      }
      //if it's exist convertView then consume it
      else {
       holder =(ViewHolder) convertView.getTag();
      }  
      //set data to holder
      if(data.get(position).isAdmin())
      {
       holder.image.setImageResource(R.drawable.admin);
      }
      else{
       holder.image.setImageResource(R.drawable.user);
      }
      holder.name.setText((CharSequence) data.get(position).getName());
      holder.address.setText((CharSequence) data.get(position).getAddress());
      //return ListView item
      return convertView;
     }
     //ViewHolder class that hold over ListView Item 
     static class ViewHolder{
      ImageView image;
      TextView name;
      TextView address;
     }
    }
    
    Here I use few considerable thing when implementing Adapter.One thing is ViewHolder class that hold all the data for our ListView item.Here you can see I got convertView, inflating my employer_list_item.xml. Inflating and findViewById operation is consume lot power and memory.So I create that only one time.If it exists already I use it not going to create it every time.This also use for ViewHolder items also.Only one time create all ViewHolder items from resource and then we use it.In this implementation we assign data to views each and every time when new data comes.So because of that we improve efficiency of Our ListView correctly. 
  4. Finally I'm going Implement ListActivity so I change my Activity extending ListActivity as following.
    import java.util.ArrayList;
    import java.util.List;
    import android.app.ListActivity;
    import android.os.Bundle;
    public class AndroidListViewExampleActivity extends ListActivity {
        /** Called when the activity is first created. */
     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            //create employee list
            List<Employer> data = new ArrayList<Employer>();
            //add data to list here I create admin for every odd number
            for (int i = 0; i < 100; i++) {
             data.add(new Employer("Employer " +i, "Address " +i,(i%2==0)? false:true));
      }
            //this is final step.i create EmployerArrayAdapter with this context 
            //and data list and set it as ListAdapter
            setListAdapter(new EmployerArrayAdapter(this, data));
        }
    }
    finally I create dummy employer list then pass it to our ArrayAdapter and set this adapter as ListAdapter.

You can download code here and if you have any problem on this please inform me commenting here.