I am building an sms app which lists the contact pic,name,message,date of a conversation. I'm using a custom adapter to list them.Below is the code
public class ConvRowAdapter extends ArrayAdapter<ConvItem> {
private Context my_context;
// View lookup cache
private static class ViewHolder {
    TextView name,body,date;
    ImageView img;
}
public ConvRowAdapter(Context context, ArrayList<ConvItem> ConvItems) {
   super(context, R.layout.convitem, ConvItems);
   my_context=context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
   // Get the data item for this position
   ConvItem ConvItem = getItem(position);    
   // Check if an existing view is being reused, otherwise inflate the view
   ViewHolder viewHolder; // view lookup cache stored in tag
   if (convertView == null) {
      viewHolder = new ViewHolder();
      LayoutInflater inflater = LayoutInflater.from(getContext());
      convertView = inflater.inflate(R.layout.convitem, null);
      viewHolder.img = (ImageView) convertView.findViewById(R.id.iv_photo);
      viewHolder.name = (TextView) convertView.findViewById(R.id.tv_name);
      viewHolder.date = (TextView) convertView.findViewById(R.id.tv_date);
      viewHolder.body = (TextView) convertView.findViewById(R.id.tv_body);
      convertView.setTag(viewHolder);
   } else {
       viewHolder = (ViewHolder) convertView.getTag();
   }
   // Populate the data into the template view using the data object
   if(ConvItem.getPhotoUri()!=null)
   {
       Bitmap bitmap=BitmapFactory.decodeStream(my_context.getContentResolver().openInputStream(ConvItem.getPhotoUri()));
       viewHolder.img.setImageBitmap(bitmap);//Image is set
   }
   else
   {
       Bitmap bitmap=BitmapFactory.decodeResource(my_context.getResources(),R.drawable.contact_blue);
       viewHolder.img.setImageBitmap(bitmap);
   }
   if(ConvItem.getDisplayName()==null)
   viewHolder.name.setText(ConvItem.getAddress());//Phone number set
   else
   viewHolder.name.setText(ConvItem.getDisplayName());//If phone number exists in contacts display contact name
   viewHolder.date.setText(ConvItem.getDate());//set date
   viewHolder.body.setText(ConvItem.getBody());//setting the body of the message
   // Return the completed view to render on screen
   return convertView;
}
}
It takes 8-9 seconds to display the list. Is there a way to improve the speed? If so please post the correct way to do so.
Thanks in advance :)
Edited:
To check if the delay in loading is caused by the loading of images i tried deleting all photo setting statements and ran it.Still the loading takes the same time. By using a simplecursoradapter i could display the body,date and message in no delay.But to display the photo with them i tried using the custom adapter. This is the function which returns all sms into an arraylist.Please check the efficiency of the code:
public ArrayList<ConvItem> getSMS(){
    ArrayList<ConvItem> ConvItems = new ArrayList<ConvItem>();
    Uri uriSMSURI = Uri.parse("content://mms-sms/conversations?simple=true");
    Cursor cur = getActivity().getContentResolver().query(uriSMSURI, null, null, null,
            "date desc");
    cur.moveToFirst();
    while (!cur.isAfterLast()) {
        ConvItem ConvItem = new ConvItem();
        String address = null, body = null, dname = null,res=null,id_dummy=null;
        Long date=null;
        Uri uriphotoid=null;
        //to obtain address from canonical-addresses
        res = cur.getString(cur.getColumnIndex("recipient_ids"));
        Uri ad =Uri.parse("content://mms-sms/canonical-addresses/");
        Cursor curad=getActivity().getContentResolver().query(ad, null,null, null, null);
        curad.moveToFirst();
        while(!curad.isAfterLast())
        {
            id_dummy=curad.getString(curad.getColumnIndexOrThrow("_id"));
            if(id_dummy.equals(res))
            address=curad.getString(curad.getColumnIndexOrThrow("address"));
            curad.moveToNext();
        }
        curad.close();
        body = cur.getString(cur.getColumnIndexOrThrow("snippet"));
        date = cur.getLong(cur.getColumnIndexOrThrow("date"));
        Date datenew=new Date(date);
        String formatted_date=new SimpleDateFormat("  "+"dd/MM/yyyy").format(datenew);
        thread_id = cur.getString(cur.getColumnIndexOrThrow("_id"));
        Long ContactID = fetchContactIdFromPhoneNumber(address);
        //uriphotoid = getPhotoUri(ContactID);
        dname = getcontactname(address);
        ConvItem.setDisplayName(dname);
        ConvItem.setThreadId(thread_id);
        ConvItem.setAddress(address);
        //ConvItem.setPhotoUri(uriphotoid);
        ConvItem.setDate(formatted_date);
        ConvItem.setBody(body);
        ConvItems.add(ConvItem);
        cur.moveToNext();
    }
    cur.close();
    return ConvItems;
    }
This function is running on my onCreate method in the main activity class.
I used loader.callbacks to correct the delay issue.
public class InboxLoaderFragment extends Fragment implements LoaderCallbacks<Cursor>{
private static final int LOADER_ID = 1;//identify which loader
LoaderManager lm;
SimpleCursorAdapter mAdapter;
ListView lv;
private LoaderManager.LoaderCallbacks<Cursor> mCallbacks;
public InboxLoaderFragment(){}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootview=inflater.inflate(R.layout.inboxloaderfragment,container,false);  
    lv=(ListView)rootview.findViewById(R.id.list);
    // Create an empty adapter we will use to display the loaded data.
    String[] uiBindFrom = {"recipient_ids","recipient_ids","snippet"};
    int[] uiBindTo = {R.id.iv_photo,R.id.tv_name,R.id.tv_body};
    mAdapter = new SimpleCursorAdapter(getActivity(),R.layout.convitem,null,uiBindFrom,uiBindTo, 0);
    mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
        @Override
        public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
            switch(view.getId()) 
            {
            case R.id.iv_photo:
                String res=null,address=null;
                //to obtain address from canonical-addresses
                res = cursor.getString(cursor.getColumnIndex("recipient_ids"));
                address=getadd(res);
                Long ContactID = fetchContactIdFromPhoneNumber(address);
                Uri uriphotoid = getPhotoUri(ContactID);
                setcontactimage(uriphotoid,view);
                //set photo using uri
                return true;
            case R.id.tv_name:
                String res1=null,address1=null;
                res1 = cursor.getString(cursor.getColumnIndex("recipient_ids"));
                address1=getadd(res1);//to obtain address from canonical-addresses
                String dname = getcontactname(address1);
                if(dname!=null)//contact exits
                ((TextView)view).setText(dname);//contact exists
                else
                ((TextView)view).setText(address1);//set display name
                return true;
            case R.id.tv_body:
                String body = cursor.getString(cursor.getColumnIndexOrThrow("snippet"));
                ((TextView)view).setText(body);//set message body
                return true;
            default:
            return false;
            }
        }
    });
    lv.setAdapter(mAdapter);
    mCallbacks=this;
    lm = getLoaderManager();
    //Initiating the loader
    lm.initLoader(LOADER_ID, null,mCallbacks);
    return rootview;
}
@Override
public android.support.v4.content.Loader<Cursor> onCreateLoader(
        int arg0, Bundle arg1) {
    Uri baseUri = Uri.parse("content://mms-sms/conversations?simple=true");
    return new CursorLoader(getActivity(), baseUri,
               null, null, null,"date desc");
}
@Override
public void onLoadFinished(
        android.support.v4.content.Loader<Cursor> arg0, Cursor arg1) {
    switch (arg0.getId()) {
      case LOADER_ID:
        mAdapter.swapCursor(arg1);
        break;
    }
    // The listview now displays the queried data
}
@Override
public void onLoaderReset(android.support.v4.content.Loader<Cursor> arg0) {
    mAdapter.swapCursor(null);
}
}///main activity
App loads very fast now.But scrolling is laggy.How to implement viewholder design pattern inside a custom simplecursoradapter or a cursoradapter?
 
    