Contacts解析
显示联系人
相关类
packages/apps/Contacts/src/com/android/contacts/activities/PeopleActivity.java
packages/apps/Contacts/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
packages/apps/Contacts/src/com/android/contacts/list/DefaultContactListAdapter.java
packages/apps/Contacts/src/com/android/contacts/list/ContactEntryListFragment.java
packages/apps/Contacts/src/com/android/contacts/list/ContactEntryListAdapter.java
packages/apps/Contacts/src/com/android/contacts/list/DirectoryPartition.java
packages/apps/Contacts/src/com/android/contacts/list/DirectoryListLoader.java
packages/apps/Contacts/src/com/android/contacts/quickcontact/QuickContactActivity.java
packages/apps/Contacts/src/com/android/contacts/model/ContactLoader.java
联系人列表数据加载流程
打开Contacts根目录下的AndroidManifest.xml文件查看PeopleActivity属性如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<activity
android:name=".activities.PeopleActivity"
android:alwaysRetainTaskState="true"
android:launchMode="singleTop"
android:resizeableActivity="true"
android:theme="@style/LaunchScreenTheme"
android:visibleToInstantApps="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.APP_CONTACTS"/>
</intent-filter>
PeopleActivity是Contacts应用的LAUNCHER界面,因此打开联系人应用,首先加载PeopleActivity,在createViewsAndFragments()方法中创建联系人界面
setUpListFragment()方法中创建DefaultContactBrowseListFragment所有联系人的Fragment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void setUpListFragment(FragmentManager fragmentManager) {
mContactsListFragment = (DefaultContactBrowseListFragment)
fragmentManager.findFragmentByTag(TAG_ALL);
//判断mContactsListFragment为空则创建Fragment
if (mContactsListFragment == null) {
mContactsListFragment = new DefaultContactBrowseListFragment();
mContactsListFragment.setAnimateOnLoad(true);
fragmentManager.beginTransaction()
.add(R.id.contacts_list_container, mContactsListFragment, TAG_ALL)
.commit();
fragmentManager.executePendingTransactions();
}
//对Fragment进行初始化的一系列设置
mContactsListFragment.setContactsAvailable(areContactsAvailable());
mContactsListFragment.setListType(mContactListFilterController.getFilterListType());
mContactsListFragment.setParameters(/* ContactsRequest */ mRequest,
/* fromOnNewIntent */ false);
}
创建所有联系人界面以后进行数据加载,数据加载使用DirectoryListLoader,该加载器继承自系统的AsyncTaskLoader加载器
DirectoryListLoader加载数据的Uri并非来自DirectoryPartition.mContentUri,而是直接从ContactContacts中的Directory类中获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private static final class DirectoryQuery {
//查询数据排序规则
public static final String ORDER_BY = Directory._ID;
//查询条件规则
public static final String[] PROJECTION = {
Directory._ID,
Directory.PACKAGE_NAME,
Directory.TYPE_RESOURCE_ID,
Directory.DISPLAY_NAME,
Directory.PHOTO_SUPPORT,
};
public static final int ID = 0;
public static final int PACKAGE_NAME = 1;
public static final int TYPE_RESOURCE_ID = 2;
public static final int DISPLAY_NAME = 3;
public static final int PHOTO_SUPPORT = 4;
//获取查询Uri,跟踪代码可知,Directory.ENTERPRISE_CONTENT_URI是Android 25版本之后才加入的
//ContactsUtils.java
//public static final boolean FLAG_N_FEATURE = Build.VERSION.SDK_INT >= 24;
public static Uri getDirectoryUri(int mode) {
if (mode == SEARCH_MODE_DATA_SHORTCUT || mode == SEARCH_MODE_CONTACT_SHORTCUT) {
return Directory.CONTENT_URI;
} else {
return DirectoryCompat.getContentUri();
}
}
}
DirectoryPartition类对联系人数据加载过程信息进行管理,联系人信息加载后在内存中的缓存的封装,内部提供了3种数据加载信息状态
1
2
3
public static final int STATUS_NOT_LOADED = 0; //还未加载数据
public static final int STATUS_LOADING = 1; //正在加载数据
public static final int STATUS_LOADED = 2; //数据已加载完毕
联系人详情页加载流程
联系人详情的界面类是QuickContactActivity,一般情况下联系人详情是通过其他入口启动的,启动时必须通过Intent传递lookupUri到QuickContactActivity,否则将调用finish()关闭界面
联系人详情数据加载流程中的加载器ContactLoader和列表一样都继承自AsyncTaskLoader,可查看代码了解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private void processIntent(Intent intent) {
//这里各种判断中调用finish(),就是对加载联系人合法性的判断失败后自己关闭界面
......
//使用oldLookupUri,对加载过的联系人进行缓存,以便再次打开能更快加载
mLookupUri = lookupUri;
mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES);
if (oldLookupUri == null) {
// Should not log if only orientation changes.
mShouldLog = !mIsRecreatedInstance;
mContactLoader = (ContactLoader) getLoaderManager().initLoader(
LOADER_CONTACT_ID, null, mLoaderContactCallbacks);
} else if (oldLookupUri != mLookupUri) {
// Should log when reload happens, regardless of orientation change.
mShouldLog = true;
// After copying a directory contact, the contact URI changes. Therefore,
// we need to reload the new contact.
destroyInteractionLoaders(http://www.amjmh.com/v/BIBRGZ_558768/);
mContactLoader = (ContactLoader) (Loader<?>) getLoaderManager().getLoader(
LOADER_CONTACT_ID);
mContactLoader.setNewLookup(mLookupUri);
mCachedCp2DataCardModel = null;
}
//最后通过ContactLoader开启联系人数据加载
mContactLoader.forceLoad();
}
————————————————