解决方案

Android ContactsProvider源码分析

seo靠我 2023-09-23 15:19:13

Android源码目录packages\providers下的应用是下载,通话等内置基本应用提供数据存储和操作的provider应用,本文章将针对ContactsProvider源码的架构和实现展开分SEO靠我析。(注:本文使用使用android4.0版本进行分析)

1、架构设计

ContactsProvider中数据操作基类是AbstractContactsProvider.java(参见frameworksSEO靠我\ex\common\java\com\android\common\content\SQLiteContentProvider.java),它继承ContentProvider.java实现SQLiSEO靠我teTransactionListener.java,类结构如下图所示:

图 1 provider结构图

该类是抽象基类,在里面实现了父类的insert、delete和update三个抽象方法,在这三个方SEO靠我法中在其中使用了事务对数据库进行操作。该类设计时,使用了模板模式模板方法为insertInTransaction,updateInTransaction和deleteInTransaction。该类在SEO靠我对数据库进行事务操作的同时,对子类开放了onRollback,onCommit等事物回调方法,子类可以根据自己的业务特点进行扩展。增删改查的调用过程如下图2 3 4所示:

图2  插入操作

图 3 更新操SEO靠我

图 4 删除操作

在整个设计中有两个类继承了AbstractContactsProvider.java,一个是ContactsProvider2.java,我们在调用系统的联系人数据时基本都是调用该类SEO靠我,里面封装了所有联系人的数据操作。第二个是ProfileProvider.java,该类是ContactsProvider2.java的委托类。这三个类的类间关系如下图5所示:

图 5 类间关系图

类CoSEO靠我ntactsTransaction.java是对事务的管理类,主要对进行的事务进行管理,类似一个事务池。是AbstractContactsProvider.java中事务处理的核心类。

DataRowHSEO靠我andler.java是数据处理抽象类,实现了对数据的增删改操作,子类有如下几个:

[java]view plain copy DataRowHandlerForCommonDataKind.java SEO靠我  DataRowHandlerForCustomMimetype.java   DataRowHandlerForEmail.java   DataRowHandlerForGroupMembersSEO靠我hip.java   DataRowHandlerForIm.java   DataRowHandlerForNickname.java   DataRowHandlerForNote.java   SEO靠我DataRowHandlerForOrganization.java   DataRowHandlerForPhoneNumber.java   DataRowHandlerForPhoto.javaSEO靠我   DataRowHandlerForStructuredName.java   DataRowHandlerForStructuredPostal.java

这些子类在ContactsProvideSEO靠我r2#initDataRowHandlers中初始化

[java]view plain copy private void initDataRowHandlers(Map<String, DataRowSEO靠我Handler> handlerMap,           ContactsDatabaseHelper dbHelper, ContactAggregator contactAggregator,SEO靠我           PhotoStore photoStore) {       Context context = getContext();       handlerMap.put(EmailSEO靠我.CONTENT_ITEM_TYPE,               new DataRowHandlerForEmail(context, dbHelper, contactAggregator));SEO靠我       handlerMap.put(Im.CONTENT_ITEM_TYPE,               new DataRowHandlerForIm(context, dbHelper,SEO靠我 contactAggregator));       handlerMap.put(Organization.CONTENT_ITEM_TYPE,               new DataRowSEO靠我HandlerForOrganization(context, dbHelper, contactAggregator));       handlerMap.put(Phone.CONTENT_ITSEO靠我EM_TYPE,               new DataRowHandlerForPhoneNumber(context, dbHelper, contactAggregator));     SEO靠我  handlerMap.put(Nickname.CONTENT_ITEM_TYPE,               new DataRowHandlerForNickname(context, dbSEO靠我Helper, contactAggregator));       handlerMap.put(StructuredName.CONTENT_ITEM_TYPE,               neSEO靠我w DataRowHandlerForStructuredName(context, dbHelper, contactAggregator,                       mNameSSEO靠我plitter, mNameLookupBuilder));       handlerMap.put(StructuredPostal.CONTENT_ITEM_TYPE,             SEO靠我  new DataRowHandlerForStructuredPostal(context, dbHelper, contactAggregator,                       SEO靠我mPostalSplitter));       handlerMap.put(GroupMembership.CONTENT_ITEM_TYPE,               new DataRowSEO靠我HandlerForGroupMembership(context, dbHelper, contactAggregator,                       mGroupIdCache)SEO靠我);       handlerMap.put(Photo.CONTENT_ITEM_TYPE,               new DataRowHandlerForPhoto(context, dSEO靠我bHelper, contactAggregator, photoStore));       handlerMap.put(Note.CONTENT_ITEM_TYPE,              SEO靠我 new DataRowHandlerForNote(context, dbHelper, contactAggregator));   }

这些子类在getDataRowHandler方法中中通过miSEO靠我metype进行调用:

[java]view plain copy public DataRowHandler getDataRowHandler(final String mimeType) {   SEO靠我    if (inProfileMode()) {           return getDataRowHandlerForProfile(mimeType);       }       DatSEO靠我aRowHandler handler = mDataRowHandlers.get(mimeType);       if (handler == null) {           handlerSEO靠我 = new DataRowHandlerForCustomMimetype(                   getContext(), mContactsHelper, mContactAggSEO靠我regator, mimeType);           mDataRowHandlers.put(mimeType, handler);       }       return handler;SEO靠我   }

getDataRowHandler方法在insertData,deleteData和updateData方法中被调用。

[java]view plain copy /**      * InseSEO靠我rts an item in the data table      *      * @param values the values for the new row      * @return SEO靠我the row ID of the newly created row      */      private long insertData(ContentValues values, booleSEO靠我an callerIsSyncAdapter) {          long id = 0;          mValues.clear();          mValues.putAll(vaSEO靠我lues);          long rawContactId = mValues.getAsLong(Data.RAW_CONTACT_ID);          // Replace packSEO靠我age with internal mapping          final String packageName = mValues.getAsString(Data.RES_PACKAGE);SEO靠我          if (packageName != null) {              mValues.put(DataColumns.PACKAGE_ID, mDbHelper.get(SEO靠我).getPackageId(packageName));          }          mValues.remove(Data.RES_PACKAGE);          // ReplSEO靠我ace mimetype with internal mapping          final String mimeType = mValues.getAsString(Data.MIMETYPSEO靠我E);          if (TextUtils.isEmpty(mimeType)) {              throw new IllegalArgumentException(DataSEO靠我.MIMETYPE + " is required");          }          mValues.put(DataColumns.MIMETYPE_ID, mDbHelper.get(SEO靠我).getMimeTypeId(mimeType));          mValues.remove(Data.MIMETYPE);          DataRowHandler rowHandlSEO靠我er = <span style="color: rgb(102, 102, 204);">getDataRowHandler(mimeType)</span>;          id = rowHSEO靠我andler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues);          if (!callSEO靠我erIsSyncAdapter) {              mTransactionContext.get().markRawContactDirty(rawContactId);        SEO靠我  }          mTransactionContext.get().rawContactUpdated(rawContactId);          return id;      }

所有SEO靠我数据的mimetype都被存储在表Tables.MIMETYPES中,该只有两个字段_id和mimetype。

[java]view plain copy db.execSQL("CREATE TABLSEO靠我E " + Tables.MIMETYPES + " ("                 + MimetypesColumns._ID + " INTEGER PRIMARY KEY AUTOINCSEO靠我REMENT,"                 + MimetypesColumns.MIMETYPE + " TEXT NOT NULL" + ");");

Tables.MIMETYPES表数据的SEO靠我存储是在ContactsDatabaseHelper#lookupAndCacheId中进行的,具体调用过程如下图 6 所示:

图 6 mimetype数据调用流程图

2、表结构

ContactsProviSEO靠我der 中共创建了25张表,

[java]

view plain copy public static final String CONTACTS = "contacts";   public statiSEO靠我c final String RAW_CONTACTS = "raw_contacts";   public static final String STREAM_ITEMS = "stream_itSEO靠我ems";   public static final String STREAM_ITEM_PHOTOS = "stream_item_photos";   public static final SEO靠我String PHOTO_FILES = "photo_files";   public static final String PACKAGES = "packages";   public staSEO靠我tic final String MIMETYPES = "mimetypes";   public static final String PHONE_LOOKUP = "phone_lookup"SEO靠我;   public static final String NAME_LOOKUP = "name_lookup";   public static final String AGGREGATIONSEO靠我_EXCEPTIONS = "agg_exceptions";   public static final String SETTINGS = "settings";   public static SEO靠我final String DATA = "data";   public static final String GROUPS = "groups";   public static final StSEO靠我ring PRESENCE = "presence";   public static final String AGGREGATED_PRESENCE = "agg_presence";   pubSEO靠我lic static final String NICKNAME_LOOKUP = "nickname_lookup";   public static final String CALLS = "cSEO靠我alls";   public static final String STATUS_UPDATES = "status_updates";   public static final String SEO靠我PROPERTIES = "properties";   public static final String ACCOUNTS = "accounts";   public static finalSEO靠我 String VISIBLE_CONTACTS = "visible_contacts";   public static final String DIRECTORIES = "directoriSEO靠我es";   public static final String DEFAULT_DIRECTORY = "default_directory";   public static final StrSEO靠我ing SEARCH_INDEX = "search_index";   public static final String VOICEMAIL_STATUS = "voicemail_statusSEO靠我";

这些表数据对开发者开放的api在 \frameworks\base\core\java\android\provider\文件夹下, [java]view plain copy CallLog.jaSEO靠我va   Contacts.java   ContactsContract.java   SocialContract.java   SyncConstValue.java   VoicemailCoSEO靠我ntract.java

由于数据查询涉及多个表间关系,大量数据的查询都是通过视图来完成的,创建了如下8个视图,而这几个视图是大家在调用api进行查询时显示的数据:

[java]view plain copSEO靠我y public interface Views {       public static final String DATA = "view_data";       public static SEO靠我final String RAW_CONTACTS = "view_raw_contacts";       public static final String CONTACTS = "view_cSEO靠我ontacts";       public static final String ENTITIES = "view_entities";       public static final StrSEO靠我ing RAW_ENTITIES = "view_raw_entities";       public static final String GROUPS = "view_groups";    SEO靠我   public static final String DATA_USAGE_STAT = "view_data_usage_stat";       public static final StSEO靠我ring STREAM_ITEMS = "view_stream_items";   }

4、总结

ContactsProvder是provider源码中数据处理和架构比较全面的一个应用,可以将它的架构核SEO靠我心抽离出来供大家参考和借鉴,以下类构成了整个架构的核心类,可以重点研究:

[java]view plain copy AbstractContactsProvider.java   ContactAggSEO靠我regator.java   ContactsDatabaseHelper.java   ContactsProvider2.java   ContactsTransaction.java   TraSEO靠我nsactionContext.java
“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2