3,contacts加载联系人
Contacts加载和搜索联系人都是同一个MultiSelectContactsListFragment。架构图如下,
3.1 初始化
MultiSelectContactsListFragment的createListAdapter方法如下,
DefaultContactListAdapter adapter = new MultiSelectEntryContactListAdapter(getContext());
adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
adapter.setDisplayPhotos(true);
adapter.setPhotoPosition(
ContactListItemView.getDefaultPhotoPosition(/* opposite = */ false));
return adapter;
因此, MultiSelectContactsListFragment对应的adapter为MultiSelectEntryContactListAdapter。
父类DefaultContactBrowseListFragment的createCursorLoader方法如下,
return new ProfileAndContactsLoader(context);
因此, MultiSelectContactsListFragment对应的CursorLoader是ProfileAndContactsLoader。
ProfileAndContactsLoader比较简单,仅仅继承了CursorLoader,
public class ProfileAndContactsLoader extends CursorLoader {
实现了loadInBackground方法,这个方法在查询过程中调用。
3.2 查询过程
在PeopleActivity界面中,查询输入控件在 ActionBarAdapter中加载并显示, ActionBarAdapter的setupSearchAndSelectionViews方法有关代码如下,
mSearchView = (EditText) mSearchContainer.findViewById(R.id.search_view);
mSearchView.setHint(mActivity.getString(R.string.hint_findContacts));
mSearchView.addTextChangedListener(new SearchTextWatcher());
SearchTextWatcher是ActionBarAdapter的内部类,实现了TextWatcher接口的三个方法,
也就是说,如果mSearchView控件的字符发送变化,则会回调SearchTextWatcher的方法,
其onTextChanged方法主要逻辑如下,
1,获取控件的字符串,
if (queryString.equals(mQueryString)) {
return;
}
mQueryString = queryString.toString();
2,如果不是查询模式,就设置为查询模式,
if (!mSearchMode) {
if (!TextUtils.isEmpty(queryString)) {
setSearchMode(true);
}
•••
3,如果是查询模式,回调接口的onAction方法处理CHANGE_SEARCH_QUERY消息,
else if (mListener != null) {
mListener.onAction(Action.CHANGE_SEARCH_QUERY);
}
查询调用流程图如下,
PeopleActivity的onAction方法对CHANGE_SEARCH_QUERY处理如下,
case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
final String queryString = mActionBarAdapter.getQueryString();
setQueryTextToFragment(queryString);
•••
break;
setQueryTextToFragment方法如下,
mAllFragment.setQueryString(query, true);
前面论述过,如果调用ContactEntryListAdapter的setQueryString方法, 最后会调用LoaderManager的initLoader方法就开始查询。
ContactEntryListFragment的onCreateLoader方法最后会调用mAdapter的configureLoader方法, DefaultContactListAdapter的configureLoader方法主要是为ProfileAndContactsLoader设置查询的参数,主要逻辑如下,
1,设置setLoadProfile
if (loader instanceof ProfileAndContactsLoader) {
((ProfileAndContactsLoader) loader).setLoadProfile(shouldIncludeProfile());
}
2,根据不同的情况设置查询模式的参数.
A,获取查询的字符串
String query = getQueryString();
if (query == null) {
query = "";
}
query = query.trim();
B,然后以下5种情况设置ProfileAndContactsLoader的查询参数
根据字符串是否为空分别设置ProfileAndContactsLoader的参数;
根据是否是飞行模式,查询SIM卡联系人读取设置不同参数。
不是查询模式的情况下设置参数。
例如,在查询模式下,字符串为空,设置参数如下,
loader.setUri(Contacts.CONTENT_URI);
loader.setProjection(getProjection(false));
loader.setSelection("0");
3,设置查询顺序
loader.setSortOrder(sortOrder);
在此可以看到,查询的是contacts2.db数据库。
查询时会调用ProfileAndContactsLoader的loadInBackground方法,基本也是调用父类的loadInBackground方法进行查询,
cursor = super.loadInBackground();
查询完成之后,也是封装成MergeCursor返回,
final Cursor contactsCursor = cursor;
cursors.add(contactsCursor);
return new MergeCursor(cursors.toArray(new Cursor[cursors.size()])) {
@Override
public Bundle getExtras() {
// Need to get the extras from the contacts cursor.
return contactsCursor == null ? new Bundle() : contactsCursor.getExtras();
}
};