Search code examples
androidandroid-cursorloader

Displaying wrong contact photo while scrolling listview


I am developing one Loaders & list view simple app. It is exactly like whatsapp's CONTACTS tab list. This app get the contacts from mobile and displays the name and image in list item. You can find the fragment code here.

import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;

import java.io.InputStream;


public class TabThreeFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

    MyCursorAdapter mAdapter;
    SimpleCursorAdapter s;
    public static final  String TAG = "TabThreeFragment";

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        setEmptyText("No phone numbers");

        mAdapter  = new MyCursorAdapter(getActivity(), R.layout.contact_list_item, null, 0 );

        setListAdapter(mAdapter);

        getLoaderManager().initLoader(0, null, this);
    }

    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME,
            ContactsContract.Contacts.CONTACT_STATUS,
            ContactsContract.Contacts.CONTACT_PRESENCE,
            ContactsContract.Contacts.PHOTO_ID,
            ContactsContract.Contacts.LOOKUP_KEY,
    };

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {

        Log.d(TAG, "onCreateLoader");
        Uri baseUri = ContactsContract.Contacts.CONTENT_URI;

        String select = "((" + ContactsContract.Contacts.DISPLAY_NAME + " NOTNULL) AND ("
                + ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                + ContactsContract.Contacts.DISPLAY_NAME + " != '' ))";

        return new CursorLoader(getActivity(), baseUri,
                CONTACTS_SUMMARY_PROJECTION, select, null,
                ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        Log.d(TAG, "onLoadFinished");
        mAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mAdapter.swapCursor(null);
    }


    class MyCursorAdapter extends ResourceCursorAdapter{

        public MyCursorAdapter(Context context, int layout, Cursor c, int flags) {
            super(context, layout, c, flags);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            TextView contactName = (TextView) view.findViewById(R.id.textView1);
            contactName.setText(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));

            ImageView imageView = (ImageView) view.findViewById(R.id.profileImage);
            Bitmap profileImage = getPhoto(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)));

            //TextView ID = (TextView) view.findViewById(R.id.textView2);
            if(profileImage !=null)
            {
                 imageView.setImageBitmap(profileImage);
            }
        }

        private Bitmap getPhoto(String id){
            Log.d(TAG, id + "-----");
            Bitmap photo = null;
            try{
                InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(
                        getActivity().getContentResolver(),
                        ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI , new Long(id).longValue()));
                if(inputStream != null)
                    photo= BitmapFactory.decodeStream(inputStream);
            }catch (Exception e){

            }
            return photo;
        }
    }
}

List Item Layout file:- contact_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="wrap_content" android:gravity="center_vertical" android:layout_marginLeft="8dp"
    android:layout_marginRight="8dp" android:layout_marginTop="6dp" android:layout_marginBottom="6dp">

    <ImageView android:id="@+id/profileImage"
        android:src="@drawable/ic_launcher"
        android:layout_weight="0"  android:layout_width="50dp"
        android:layout_height="50dp"/>

    <LinearLayout android:orientation="vertical"
        android:layout_weight="1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="6dp"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Medium Text"
            android:id="@+id/textView1" />

        <TextView
            android:id="@+id/textView2"
            android:paddingLeft="6dp"
            android:textSize="16dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Dummy Content fro subtile"
           />

    </LinearLayout>>

</LinearLayout>

My problem, app is displayed the contact details and photos but photos are changing every time when I scroll up and down. It means one contact information displaying with other contact's photo.

Did I miss anything?


Solution

  • use

    if(profileImage !=null){
          imageView.setImageBitmap(profileImage);
    }else{
          imageView.setImageDrawable(null);
    }
    

    inside your getview()