1 package com.android.ex.chips; 2 3 import android.net.Uri; 4 import android.provider.ContactsContract.CommonDataKinds.Email; 5 import android.provider.ContactsContract.DisplayNameSources; 6 7 /** 8 * Represents one entry inside recipient auto-complete list. 9 */ 10 public class RecipientEntry { 11 /* package */ static final int INVALID_CONTACT = -1; 12 /** 13 * A GENERATED_CONTACT is one that was created based entirely on 14 * information passed in to the RecipientEntry from an external source 15 * that is not a real contact. 16 */ 17 /* package */ static final int GENERATED_CONTACT = -2; 18 19 /** Used when {@link #mDestinationType} is invalid and thus shouldn't be used for display. */ 20 /* package */ static final int INVALID_DESTINATION_TYPE = -1; 21 22 public static final int ENTRY_TYPE_PERSON = 0; 23 24 public static final int ENTRY_TYPE_SIZE = 1; // 这是什么类型? 25 26 private final int mEntryType; // 这是用来表征哪种分类方法的? 27 28 /** 29 * True when this entry is the first entry in a group, which should have a photo and display 30 * name, while the second or later entries won't. 31 */// 涉及到了 group 分组的概念,entry 是怎么分组的?为什么要分组? 32 private boolean mIsFirstLevel; 33 private final String mDisplayName; 34 35 /** Destination for this contact entry. Would be an email address or a phone number. */ 36 private final String mDestination; 37 /** Type of the destination like {@link Email#TYPE_HOME} */ 38 private final int mDestinationType; 39 /** 40 * Label of the destination which will be used when type was {@link Email#TYPE_CUSTOM}. 41 * Can be null when {@link #mDestinationType} is {@link #INVALID_DESTINATION_TYPE}. 42 */// 干嘛用的,应该不是用来显示的呀,显示不是已经有displayName了吗? 43 private final String mDestinationLabel; 44 /** ID for the person */ 45 private final long mContactId; 46 /** ID for the destination */ 47 private final long mDataId; 48 private final boolean mIsDivider; 49 50 private final Uri mPhotoThumbnailUri; 51 52 /** 53 * This can be updated after this object being constructed, when the photo is fetched 54 * from remote directories. 55 */ 56 private byte[] mPhotoBytes; 57 58 private RecipientEntry(int entryType) { 59 mEntryType = entryType; 60 mDisplayName = null; 61 mDestination = null; 62 mDestinationType = INVALID_DESTINATION_TYPE; 63 mDestinationLabel = null; 64 mContactId = -1; 65 mDataId = -1; 66 mPhotoThumbnailUri = null; 67 mPhotoBytes = null; 68 mIsDivider = true; 69 } 70 71 private RecipientEntry( 72 int entryType, String displayName, 73 String destination, int destinationType, String destinationLabel, 74 long contactId, long dataId, Uri photoThumbnailUri, boolean isFirstLevel) { 75 mEntryType = entryType; 76 mIsFirstLevel = isFirstLevel; 77 mDisplayName = displayName; 78 mDestination = destination; 79 mDestinationType = destinationType; 80 mDestinationLabel = destinationLabel; 81 mContactId = contactId; 82 mDataId = dataId; 83 mPhotoThumbnailUri = photoThumbnailUri; 84 mPhotoBytes = null; 85 mIsDivider = false; 86 } 87 88 /** 89 * Determine if this was a RecipientEntry created from recipient info or 90 * an entry from contacts. 91 */ 92 public static boolean isCreatedRecipient(long id) { 93 return id == RecipientEntry.INVALID_CONTACT || id == RecipientEntry.GENERATED_CONTACT; 94 } 95 96 /** 97 * Construct a RecipientEntry from just an address that has been entered. 98 * This address has not been resolved to a contact and therefore does not 99 * have a contact id or photo. 100 */ 101 public static RecipientEntry constructFakeEntry(String address) { 102 return new RecipientEntry(ENTRY_TYPE_PERSON, address, address, 103 INVALID_DESTINATION_TYPE, null, 104 INVALID_CONTACT, INVALID_CONTACT, null, true); 105 } 106 107 /** 108 * @return the display name for the entry. If the display name source is larger than 109 * {@link DisplayNameSources#PHONE} we use the contact's display name, but if not, 110 * i.e. the display name came from an email address or a phone number, we don't use it 111 * to avoid confusion and just use the destination instead. 112 */ 113 private static String pickDisplayName(int displayNameSource, String displayName, 114 String destination) { 115 return (displayNameSource > DisplayNameSources.PHONE) ? displayName : destination; 116 } 117 118 /** 119 * Construct a RecipientEntry from just an address that has been entered 120 * with both an associated display name. This address has not been resolved 121 * to a contact and therefore does not have a contact id or photo. 122 */ 123 public static RecipientEntry constructGeneratedEntry(String display, String address) { 124 return new RecipientEntry(ENTRY_TYPE_PERSON, display, 125 address, INVALID_DESTINATION_TYPE, null, 126 GENERATED_CONTACT, GENERATED_CONTACT, null, true); 127 } 128 129 public static RecipientEntry constructTopLevelEntry( 130 String displayName, int displayNameSource, String destination, int destinationType, 131 String destinationLabel, long contactId, long dataId, Uri photoThumbnailUri) { 132 return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, displayName, 133 destination), 134 destination, destinationType, destinationLabel, 135 contactId, dataId, 136 photoThumbnailUri, true); 137 } 138 139 public static RecipientEntry constructTopLevelEntry( 140 String displayName, int displayNameSource, String destination, int destinationType, 141 String destinationLabel, long contactId, long dataId, 142 String thumbnailUriAsString) { 143 return new RecipientEntry( 144 ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, displayName, destination), 145 destination, destinationType, destinationLabel, 146 contactId, dataId, 147 (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString) : null), true); 148 } 149 150 public static RecipientEntry constructSecondLevelEntry( 151 String displayName, int displayNameSource, String destination, int destinationType, 152 String destinationLabel, long contactId, long dataId, String thumbnailUriAsString) { 153 return new RecipientEntry( 154 ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, displayName, destination), 155 destination, destinationType, destinationLabel, 156 contactId, dataId, 157 (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString) : null), false); 158 } 159 160 public int getEntryType() { 161 return mEntryType; 162 } 163 164 public String getDisplayName() { 165 return mDisplayName; 166 } 167 168 public String getDestination() { 169 return mDestination; 170 } 171 172 public int getDestinationType() { 173 return mDestinationType; 174 } 175 176 public String getDestinationLabel() { 177 return mDestinationLabel; 178 } 179 180 public long getContactId() { 181 return mContactId; 182 } 183 184 public long getDataId() { 185 return mDataId; 186 } 187 188 public boolean isFirstLevel() { 189 return mIsFirstLevel; 190 } 191 192 public Uri getPhotoThumbnailUri() { 193 return mPhotoThumbnailUri; 194 } 195 196 /** This can be called outside main Looper thread. */ 197 public synchronized void setPhotoBytes(byte[] photoBytes) { 198 mPhotoBytes = photoBytes; 199 } 200 201 /** This can be called outside main Looper thread. */ 202 public synchronized byte[] getPhotoBytes() { 203 return mPhotoBytes; 204 } 205 206 public boolean isSeparator() { 207 return mIsDivider; 208 } 209 210 public boolean isSelectable() { 211 return mEntryType == ENTRY_TYPE_PERSON; 212 }