系统应用新建联系人保存流程

与联系人保存相关的类有:

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方法里面,就可以把数据插入数据库了,整个流程就是这样的了

猜你喜欢

转载自blog.csdn.net/u010471406/article/details/95599607
今日推荐