【问题标题】:Load a contact's picture into ListView (part 2)将联系人的图片加载到 ListView(第 2 部分)
【发布时间】:2012-05-24 17:38:02
【问题描述】:

根据那里的答案,我已经修改了the code in this question,以便在 ListView 上加载联系人的图片。我正在获取 Photo_id,并使用它来获取联系人的位图,使用 loadContactPhoto(ContentResolver cr, long id) 。问题是没有 ImageView 正在获取新图像,尽管照片 ID 总是不同的。我尝试使用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);
}

    }

ContactListAdapter:

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
    }
}

【问题讨论】:

  • 你是怎么解决这个问题的?
  • 阅读问题的答案。我自己写了一篇,里面有你需要的所有细节和例子

标签: android image contactscontract


【解决方案1】:

您的代码中有两个问题。第一个很容易克服,其他需要更多的工作。

让我们从简单的开始: ContactsContract.Contacts.openContactPhotoInputStream(cr, uri) 方法采用联系人 uri 而不是照片 uri。也就是说,您拨打 ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id) 时的 id 必须是联系人 id。

此外,您在遍历结果集时会创建大量 Bitmap 对象。不要这样做。虽然一开始这可能有效,但当列表过长时,它可能会因OutOfMemory 错误而崩溃。尝试根据需要创建尽可能少的Bitmapobjects。即:仅适用于那些可见的行。滚动列表视图时,您必须回收现有的位图。

【讨论】:

    【解决方案2】:

    由于我在弄清楚如何有效地加载所有联系人的照片而不出现任何 UI 冻结时遇到了很多麻烦,当我第一次开始使用 Android 时加载图像时出错,我强烈建议任何查看我的问题的人好好看看here.

    这是一个示例应用程序,可教您如何处理所有处理数据并无缝加载图像,并且在滚动列表时不会出现任何“打嗝”。这也是一个让您开始在 Android 上工作的好项目!

    具体来说,对于我的问题代码中的联系人图片部分,API 提供了两个简单的方法,可以在here 找到,返回联系人的高分辨率图像或缩略图的InputStream。您所要做的就是使用BitmapFactory.decodeByteArray() 对其进行解码。请记住加载您需要在应用中使用的图像大小(在上面的链接中进行了描述),这样您就不会收到 OutOfMemoryError!

    为了进一步改进代码,还可以将ArrayAdapter替换成自定义的Cursor适配器,当场只加载需要的listView行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多