Proceso de guardado de nuevo contacto de la aplicación del sistema

Las clases relacionadas con el ahorro de contactos son:

1.ContactEditorActivity

2.ContactEditorFragment

3. ContactSaveService

Después de editar los datos en la interfaz de edición de contactos ContactEditorFragment, haga clic en Guardar, se llamará al método doSave () en ContactEditorFragment

 

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);

Creará una intención a través de ContactSaveService.createSaveContactIntent (), echemos un vistazo al proceso de creación de la intención

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

En el método createSaveContactIntent (), el nuevo método crea una intención, los parámetros dentro son un contexto y ContactSaveService, establece

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

El código central es resolver.applyBatch (), mediante depuración de errores, después de ingresar el applyBatch () de ContentResolver, un

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

Supongo que te gusta

Origin blog.csdn.net/u010471406/article/details/95599607
Recomendado
Clasificación