与联系人保存相关的类有:
1.ContactEditorActivity
2.ContactEditorFragment
3. ContactSaveService
在联系人编辑界面ContactEditorFragment编辑完数据后,点击保存,会调用ContactEditorFragment中的doSave()方法
public void doSave() {
if (mRawContactDelta != null) {
ArrayList<ValuesDelta> entrys = mRawContactDelta
.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
if (entrys != null) {
for (ValuesDelta valuesDelta : entrys) {
if (valuesDelta == null)
continue;
mEditorName = valuesDelta.getDisplayName();
}
}
}
Log.d("doSave", "mEditorName :" + mEditorName);
if (TextUtils.isEmpty(mEditorName)) {
try {
SaveNoNameDialogFragment.show(this);
} catch (Exception ignored) {
Log.d(TAG, "SaveNoNameDialogFragment----the activity is no longer available to " +
"display the dialog");
}
} else {
save(SaveMode.CLOSE);
}
}
在doSave()方法中接着调用save()方法。进入save()方法
// Save contact
Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState,
SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
((Activity) mContext).getClass(), ContactEditorActivity.ACTION_SAVE_COMPLETED,
mUpdatedPhotos, true, extraPhotoUri);
mContext.startService(intent);
会通过ContactSaveService.createSaveContactIntent()创建一个intent,我们再来看看intent的创建过程
public static Intent createSaveContactIntent(Context context, RawContactDeltaList state,
String saveModeExtraKey, int saveMode, boolean isProfile,
Class<? extends Activity> callbackActivity, String callbackAction,
Bundle updatedPhotos, boolean addAssert, String photoUri) {
Intent serviceIntent = new Intent(
context, ContactSaveService.class);
serviceIntent.setAction(ContactSaveService.ACTION_SAVE_CONTACT);
serviceIntent.putExtra(EXTRA_CONTACT_STATE, (Parcelable) state);
serviceIntent.putExtra(EXTRA_SAVE_IS_PROFILE, isProfile);
serviceIntent.putExtra(EXTRA_ADD_SAVE_ASSERT, addAssert);
if (photoUri != null) {
serviceIntent.putExtra(EXTRA_QUICK_SHOW_PHOTO_URI, photoUri);
}
if (updatedPhotos != null) {
serviceIntent.putExtra(EXTRA_UPDATED_PHOTOS, (Parcelable) updatedPhotos);
}
if (callbackActivity != null) {
// Callback intent will be invoked by the service once the contact is
// saved. The service will put the URI of the new contact as "data" on
// the callback intent.
Intent callbackIntent = new Intent(context, callbackActivity);
callbackIntent.putExtra(saveModeExtraKey, saveMode);
callbackIntent.setAction(callbackAction);
serviceIntent.putExtra(ContactSaveService.EXTRA_CALLBACK_INTENT, callbackIntent);
}
return serviceIntent;
}
在createSaveContactIntent()方法中通过new的方式创建了一个intent,里面的参数是一个context,和ContactSaveService,设置的
Action参数为ContactSaveService.ACTION_SAVE_CONTACT,通过查看ContactSaveService,我们发现ContactSaveService继承自intentService,ContactSaveService是一个service,创建完intent后接下来通过
mContext.startService(intent)启动服务
启动ContactSaveService服务后,在ContactSaveService的onHandleIntent有一系列的方法,主要有添加,修改,删除联系人等方法
@Override
protected void onHandleIntent(Intent intent) {
if (intent == null) {
return;
String action = intent.getAction();
if (ACTION_NEW_RAW_CONTACT.equals(action)) {
createRawContact(intent);
} else if (ACTION_SAVE_CONTACT.equals(action)) {
saveContact(intent);
} else if (ACTION_CREATE_GROUP.equals(action)) {
createGroup(intent);
} else if (ACTION_RENAME_GROUP.equals(action)) {
renameGroup(intent);
} else if (ACTION_DELETE_GROUP.equals(action)) {
deleteGroup(intent);
} else if (ACTION_UPDATE_GROUP.equals(action)) {
updateGroup(intent);
} else if (ACTION_SET_STARRED.equals(action)) {
setStarred(intent);
} else if (ACTION_SET_SUPER_PRIMARY.equals(action)) {
setSuperPrimary(intent);
} else if (ACTION_CLEAR_PRIMARY.equals(action)) {
clearPrimary(intent);
} else if (ACTION_DELETE_CONTACT.equals(action)) {
deleteContact(intent);
} else if (ACTION_JOIN_CONTACTS.equals(action)) {
joinContacts(intent);
} else if (ACTION_SET_SEND_TO_VOICEMAIL.equals(action)) {
setSendToVoicemail(intent);
} else if (ACTION_SET_RINGTONE.equals(action)) {
setRingtone(intent);
} else if (ACTION_DELETE_RAW_CONTACT.equals(action)) {
deleteRawContact(intent);
}
}
我们主要看saveContact()保存联系人方法,进入saveContact,一大串的代码,主要看while循环里面的代码
int tries = 0;
while (tries++ < PERSIST_TRIES) {
try {
// Build operations and try applying
final ArrayList<ContentProviderOperation> diff = state.buildDiff(hasLargePhoto(intent), isAddAssert);
if (DEBUG) {
Log.v(TAG, "Content Provider Operations:");
for (ContentProviderOperation operation : diff) {
Log.v(TAG, operation.toString());
}
}
.
.
int numberProcessed = 0;
boolean batchFailed = false;
final ContentProviderResult[] results = new ContentProviderResult[diff.size()];
while (numberProcessed < diff.size()) {
final int subsetCount = applyDiffSubset(diff, numberProcessed, results, resolver);
if (subsetCount == -1) {
Log.w(TAG, "Resolver.applyBatch failed in saveContacts");
batchFailed = true;
break;
} else {
numberProcessed += subsetCount;
}
}
在while循环中,通过RawContactDeltaList的buildDiff方法获取封装数据,联系人数据都封装到了ContentProviderOperation对象中,
具体的可以去了解ContentProviderOperation这个类和state.buildDiff()这个方法是怎么封装数据的
获取到数据后,会再次进入一个while循环,里面有个applyDiffSubset()顺着这个路线接着往下看,进入到applyDiffSubset()方法中
private int applyDiffSubset(ArrayList<ContentProviderOperation> diff, int offset,
ContentProviderResult[] results, ContentResolver resolver)
throws RemoteException, OperationApplicationException {
final int subsetCount = Math.min(diff.size() - offset, MAX_CONTACTS_PROVIDER_BATCH_SIZE);
final ArrayList<ContentProviderOperation> subset = new ArrayList<>();
subset.addAll(diff.subList(offset, offset + subsetCount));
final ContentProviderResult[] subsetResult = resolver.applyBatch(ContactsContract
.AUTHORITY, subset);
if (subsetResult == null || (offset + subsetResult.length) > results.length) {
return -1;
}
for (ContentProviderResult c : subsetResult) {
results[offset++] = c;
}
return subsetResult.length;
}
核心代码就是resolver.applyBatch(),通过debug调试,进入到ContentResolver的applyBatch()中后,会创建一个
ContentProviderClient对象provider,然后再调用provider对象的applyBatch()方法,在appLyBatch中会有一个mContentProvider,而这个对象
是通过之前ContentProviderClient provider = acquireContentProviderClient(authority)里面的的authority这个参数创建的
public final @Nullable ContentProviderClient acquireContentProviderClient(
@NonNull String name) {
Preconditions.checkNotNull(name, "name");
IContentProvider provider = acquireProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, true);
}
return null;
}
authority与之对应的provider就是我们的联系人provider,也就是说这个mContentProvider这个对象就是我们自己写的provider
public @NonNull ContentProviderResult[] applyBatch(
@NonNull ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
Preconditions.checkNotNull(operations, "operations");
beforeRemote();
try {
return mContentProvider.applyBatch(mPackageName, operations);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
}
throw e;
} finally {
afterRemote();
}
}
在ContentProviderClient里面的applyBatch中,通过mContentProvider调用applyBatch,也就是调用我们自己provider中的applyBatch方法,
在我们自定义的provider的applyBatch方法里面,就可以把数据插入数据库了,整个流程就是这样的了