使用 Picasso 加載顯示聯(lián)系人頭像

Picasso 自帶了對加載顯示聯(lián)系人頭像的支持,只要傳入聯(lián)系人頭像的 URL,例如
"photo:content://com.android.contacts/contacts/1005/photo", 再調(diào)用 Picasso.load(Uri).into(ImageView),即可完成對聯(lián)系人頭像的顯示。

但這種用法有個局限:當(dāng)我們并不知道某個聯(lián)系人的頭像 URL 時,首先得通過名字(或其他,如電話號碼)獲取到聯(lián)系人頭像的 URL,而這通常是耗時操作(查詢數(shù)據(jù)庫),需要異步進(jìn)行;這樣一來,先異步查詢出頭像 URL,再交給 Picasso 進(jìn)行異步加載并顯示,兩級異步顯得有點(diǎn)兒雞肋。所以本文除了簡單介紹

  • Picasso 自帶對聯(lián)系人頭像的支持

外,還將介紹另一種用法,

下面,我們以 根據(jù)聯(lián)系人名字獲取聯(lián)系人頭像 為例,來講解這兩種用法。

一、使用 Picasso 的內(nèi)置支持來加載

Picasso(以 2.5.2 版本為例) 總共支持 5 種聯(lián)系人頭像的 URL 格式

加載過程分以下幾步:

1. 根據(jù)名字獲取聯(lián)系人頭像的 URL

Uri elvisUrl = getContactPhotoUrl("Elvis");

/**
 * 根據(jù)名字獲取聯(lián)系人頭像的 URL。
 * @param contactName 聯(lián)系人的名字
 * @return 聯(lián)系人頭像的 URL
 */
@Nullable
public static Uri getContactPhotoUrl(Context context, String contactName) {
  Uri phoneUri = null;
  Cursor cursor = context.getContentResolver().query(
      ContactsContract.Contacts.CONTENT_URI,
      new String[]{ContactsContract.Contacts.PHOTO_URI},
      ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " = ?",
      new String[]{contactName},
      null);
  if (cursor != null) {
    try {
      if (cursor.moveToFirst()) {
        String photoUrlString = cursor.getString(0);
        if (!TextUtils.isEmpty(photoUrlString)) {
          phoneUri = Uri.parse(photoUrlString);
        }
      }
    } finally {
      cursor.close();
    }
  }
  return phoneUri;
}

2. 使用 Picasso.load(Uri).into(ImageView) 進(jìn)行顯示

mPicasso.load(elvisUrl).into(imageView);

二、使用自定義 RequestHandler 加載

1. 自定義 RequestHandler

public static final String URL_SCHEMA_CONTACT_PHOTO = "contact.photo";

private class CustomRequestHandler extends RequestHandler {
  @Override
  public boolean canHandleRequest(Request data) {
    return URL_SCHEMA_CONTACT_PHOTO.equals(data.uri.getScheme());
  }

  /**
   * 將聯(lián)系人頭像的縮略圖數(shù)據(jù)作為輸入流返回。
   */
  @Override
  public Result load(Request request, int networkPolicy) throws IOException {
    Uri uri = request.uri;
    // 從聯(lián)系人 URL 中解析出聯(lián)系人名字
    String contactName = uri.getAuthority();
    // 根據(jù)名字獲取聯(lián)系人的 Contact ID
    long contactId = getContactId(mContext, contactName);
    if (contactId <= 0) {
      return null;
    }
    // 根據(jù)聯(lián)系人的 Contact ID 獲取聯(lián)系人頭像的縮略圖數(shù)據(jù)
    byte[] photoData = loadPhotoData(mContext, contactId);
    if (photoData == null) {
      return null;
    }
    InputStream photoInputStream = new ByteArrayInputStream(photoData);
    return new Result(photoInputStream, Picasso.LoadedFrom.DISK);
  }
}

/**
 * 根據(jù)名字獲取聯(lián)系人的 Contact ID。
 *
 * @param displayName 聯(lián)系人的名字
 * @return 聯(lián)系人的 Contact ID
 */
public static long getContactId(Context context, String displayName) {
  long contactId = 0;
  ContentResolver contentResolver = context.getContentResolver();
  Uri uri = ContactsContract.Data.CONTENT_URI;
  String[] projection = new String[]{ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID};
  String selection = ContactsContract.Data.MIMETYPE + " = ? AND "
      + ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME + " = ?";
  String[] selectionArguments = {
      ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, displayName};
  Cursor cursor = contentResolver.query(uri, projection, selection, selectionArguments, null);
  if (cursor != null) {
    try {
      if (cursor.moveToFirst()) {
        contactId = cursor.getLong(0);
      }
    } finally {
      cursor.close();
    }
  }
  return contactId;
}

/**
 * 根據(jù)聯(lián)系人的 Contact ID 獲取聯(lián)系人頭像的縮略圖數(shù)據(jù)。
 *
 * @param contactId 聯(lián)系人的 Contact ID
 * @return 聯(lián)系人頭像的縮略圖數(shù)據(jù)
 */
public static byte[] loadPhotoData(Context context, long contactId) {
  byte[] photoData = null;
  Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
  Uri photoUri = Uri.withAppendedPath(contactUri,
      ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
  Cursor cursor = context.getContentResolver().query(photoUri,
      new String[]{ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
  if (cursor != null) {
    try {
      if (cursor.moveToFirst()) {
        photoData = cursor.getBlob(0);
      }
    } finally {
      cursor.close();
    }
  }
  return photoData;
}

2. 在初始化 Picasso 時添加自定義的 RequestHandler

mPicasso = new Picasso.Builder(context)
    .addRequestHandler(new CustomRequestHandler())
    ... // 省略其他配置
    .build();

3. 組裝聯(lián)系人("Elvis")的頭像 URL

/**
 * 獲取代表特定聯(lián)系人頭像縮略圖的 URL
 *
 * @param contactName 特定聯(lián)系人的顯示名
 * @return 代表特定聯(lián)系人頭像縮略圖的 URL
 */
public static Uri getContactPhotoLoadableUrl(String contactName) {
  return new Uri.Builder().scheme(URL_SCHEMA_CONTACT_PHOTO).authority(contactName).build();
}

Uri elvisUrl = getContactPhotoLoadableUrl("Elvis");

4. 使用 Picasso.load(Uri).into(ImageView) 進(jìn)行顯示

mPicasso.load(elvisUrl).into(imageView);

至此,使用 Picasso 加截顯示聯(lián)系人頭像的兩種方法已介紹完畢。大家可根據(jù)自己需求,擇其一使用。在聯(lián)系人頭像 URL 未知的情況下,優(yōu)選第二種方案,這樣可以讓聯(lián)系人的頭像加載像其他網(wǎng)絡(luò)圖片的加載一樣簡便。

關(guān)于作者
ElvisHew 的開源項目: XLog
ElvisHew 的 Github 主頁: https://github.com/elvishew
ElvisHew 的新浪微博:http://weibo.com/elvishew

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,242評論 25 708
  • 太長了,還是轉(zhuǎn)載吧...今天在看博客的時候,無意中發(fā)現(xiàn)了@Trinea在GitHub上的一個項目Android開源...
    龐哈哈哈12138閱讀 20,274評論 3 283
  • 因?yàn)?篇文章我跟下來的有6篇,認(rèn)真度又各有不同,發(fā)現(xiàn)我還是沒戰(zhàn)勝自己,擺脫虎頭蛇尾的毛病。不管怎樣,還是看下我都學(xué)...
    嘆息林上閱讀 341評論 4 1
  • 有一種人他可能會嘲諷你挖苦你譏笑你;有一種人他可能陪你笑,陪你哭,陪你鬧。但是他唯一不可能的事是拋棄你。 從小到大...
    朱程亮閱讀 340評論 0 1