Загрузите изображение контакта в ListView (часть 2)

Я изменил код в этом вопросе, согласно ответам там, чтобы загрузить изображение контакта в ListView. Я получаю Photo_id и использую его для получения растрового изображения контакта, используя loadContactPhoto(ContentResolver cr, long id) . Проблема в том, что ImageView не получает новое изображение, хотя идентификатор фотографии всегда разный. Я попытался использовать Contact._ID, но только два контакта ImageView получили изображение контакта, и они оба были неправильными. Я прокомментировал новые строки, которые я добавил ниже.

Вот код после редактирования:

КонтактыНа складе:

public class ContactStock {

private String name;
private String number;
private Bitmap picture;


public ContactStock(String name, String number) {
    this.name = name;
    this.number = number;
}

public ContactStock(String name, String number, Bitmap photo) {
    this.name = name;
    this.number = number;
    this.picture = photo;
}

public void setName(String name) {
    this.name = name;
}

public void setNumber(String number) {
    this.number = number;
}

public String getName() {
    return this.name;
}

public String getNumber() {
    return this.number;
}

public void setPicture(Bitmap picture) { // NEW METHOD
    this.picture = picture;
}

public Bitmap getPicture() { // NEW METHOD
    return picture;
}
}

добавить список из контактов:

    public class addlistfromcontact extends Activity {
private ListView lst;
private List<ContactStock> contactstock;
private Cursor mCursor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.tab_contact_list);
    lst = (ListView) findViewById(R.id.tab_contact_list);
    contactstock = new ArrayList<ContactStock>();

    mCursor = managedQuery(ContactsContract.Data.CONTENT_URI, null,
            Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", null,
            ContactsContract.Data.DISPLAY_NAME + " ASC");

    int number = mCursor.getColumnIndex(Phone.NUMBER);
    int name = mCursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
    int id = mCursor.getColumnIndex(Contacts.PHOTO_ID); // NEW LINE

    while (mCursor.moveToNext()) {

        String phName = mCursor.getString(name);
        String phNumber = mCursor.getString(number);
        long phId = mCursor.getLong(id); // NEW LINE

        Bitmap phPhoto = loadContactPhoto(getContentResolver(), phId); // NEW LINE
        Log.d("phId=", phId + "");

        contactstock.add(new ContactStock(phName, phNumber, phPhoto)); // NEW LINE EDIT
    }
    lst.setAdapter(new ContactListAdapter(addlistfromcontact.this,
            contactstock));
}

public static Bitmap loadContactPhoto(ContentResolver cr, long id) { // NEW METHOD
    Uri uri = ContentUris.withAppendedId(
            ContactsContract.Contacts.CONTENT_URI, id);
    InputStream input = ContactsContract.Contacts
            .openContactPhotoInputStream(cr, uri);
    if (input == null) {
        return null;
    }
    return BitmapFactory.decodeStream(input);
}

    }

Адаптер списка контактов:

public class ContactListAdapter extends ArrayAdapter {
    private final Activity activity;
    private final List stocks;

    public ContactListAdapter(Activity activity, List objects) {
        super(activity, R.layout.listview_detail_tab_contact_list, objects);
        this.activity = activity;
        this.stocks = objects;
    }

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

        View rowView = convertView;
        ContactStockView sv = null;
        if (rowView == null) {
            // Get a new instance of the row layout view
            LayoutInflater inflater = activity.getLayoutInflater();
            rowView = inflater.inflate(
                    R.layout.listview_detail_tab_contact_list, null);

            // Hold the view objects in an object,
            // so they don't need to be re-fetched
            sv = new ContactStockView();
            sv.name = (TextView) rowView.findViewById(R.id.contact_name);
            sv.number = (TextView) rowView.findViewById(R.id.contact_number);
            sv.photo = (ImageView) rowView.findViewById(R.id.contact_photo);

            // Cache the view objects in the tag,
            // so they can be re-accessed later
            rowView.setTag(sv);
        } else {
            sv = (ContactStockView) rowView.getTag();
        }
        // Transfer the stock data from the data object
        // to the view objects
        ContactStock currentStock = (ContactStock) stocks.get(position);
        sv.name.setText(currentStock.getName());
        sv.number.setText(currentStock.getNumber());
        sv.photo.setImageBitmap(currentStock.getPicture()); // NEW LINE

        // TODO Auto-generated method stub
        return rowView;
    }

    protected static class ContactStockView {
        protected TextView name;
        protected TextView number;
        protected ImageView photo; // NEW LINE
    }
}

person Alex Styl    schedule 24.05.2012    source источник
comment
Как вы решаете это?   -  person Hardik Joshi    schedule 14.10.2014
comment
Прочитайте ответы на вопрос. Я написал его сам со всеми деталями и примерами, которые вам нужны.   -  person Alex Styl    schedule 20.10.2014


Ответы (2)


В вашем коде две проблемы. Первую легко преодолеть, над остальными нужно поработать.

Начнем с простого: метод ContactsContract.Contacts.openContactPhotoInputStream(cr, uri) принимает uri контакта, а не uri фотографии. То есть идентификатор в вашем вызове ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id) должен быть идентификатором контакта.

Также вы создаете много объектов Bitmap при переборе набора результатов. Не делай этого. Хотя это может работать поначалу, вероятно, произойдет сбой с OutOfMemory ошибками, когда список станет слишком длинным. Постарайтесь создать как можно меньше Bitmapобъектов. То есть: только для тех строк, которые видны. При прокрутке представления списка вы должны перерабатывать существующие растровые изображения.

person Wolfram Rittmeyer    schedule 26.05.2012

Поскольку у меня было много проблем с выяснением того, как эффективно загружать фотографии всех контактов без зависания пользовательского интерфейса, ошибок при загрузке изображений, когда я впервые начал работать на Android, я настоятельно рекомендую всем, кто просматривает мой вопрос, внимательно посмотреть здесь.

Это пример приложения, которое учит вас, как обрабатывать все данные и загружать изображения плавно, эффективно, без каких-либо «заминок» при прокрутке списка. Это также отличный проект, чтобы вы начали работать на Android!

В частности, для изображения контакта в коде моих вопросов API предоставляет два простых метода, которые можно найти здесь, который возвращает InputStream изображения или миниатюры контакта в высоком разрешении. Все, что вам нужно сделать, это расшифровать его с помощью BitmapFactory.decodeByteArray(). Не забудьте загрузить размер изображения, которое вам нужно использовать в вашем приложении (что-то описано в ссылке выше), чтобы вы не получили ошибку OutOfMemoryError!

Чтобы еще больше улучшить код, вы также можете заменить ArrayAdapter пользовательским адаптером Cursor и загружать только те строки списка, которые вам нужны на месте.

person Alex Styl    schedule 07.02.2013