Now using loaders and LoaderManagingFragment
The change is partial and for now Favorites and
lots of other things are broken.
Change-Id: I8dc6104e499c094ea344f4ecd0819386150a8b0c
diff --git a/src/android/app/patterns/CursorLoader.java b/src/android/app/patterns/CursorLoader.java
index e7b2e41..04b58f5 100644
--- a/src/android/app/patterns/CursorLoader.java
+++ b/src/android/app/patterns/CursorLoader.java
@@ -138,4 +138,12 @@
public void setSelectionArgs(String[] selectionArgs) {
mSelectionArgs = selectionArgs;
}
+
+ public String getSortOrder() {
+ return mSortOrder;
+ }
+
+ public void setSortOrder(String sortOrder) {
+ mSortOrder = sortOrder;
+ }
}
diff --git a/src/android/app/patterns/LoaderManagingFragment.java b/src/android/app/patterns/LoaderManagingFragment.java
index 32e3bf3..e0a464b 100644
--- a/src/android/app/patterns/LoaderManagingFragment.java
+++ b/src/android/app/patterns/LoaderManagingFragment.java
@@ -135,7 +135,7 @@
// The loader isn't getting passed along to the next instance so ask it to stop loading
// TODO: uncomment once isChangingConfig method is available
// if (!getActivity().isChangingConfigurations()) {
-// loader.stopLoading();
+ loader.stopLoading();
// }
}
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index e1cab30..5d061f7 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -515,7 +515,8 @@
case MODE_INSERT_OR_EDIT_CONTACT:
case MODE_QUERY_PICK_TO_EDIT:
case MODE_STREQUENT:
- case MODE_FREQUENT: {
+ case MODE_FREQUENT:
+ case MODE_QUERY: {
ContactBrowseListFragment fragment = new ContactBrowseListFragment();
if (!mSearchMode) {
fragment.setSectionHeaderDisplayEnabled(true);
@@ -530,6 +531,10 @@
fragment.setCreateContactEnabled(true);
}
+ if (mMode == MODE_QUERY) {
+ fragment.setSearchResultsMode(true);
+ }
+
fragment.setOnContactListActionListener(new OnContactBrowserActionListener() {
public void onSearchAllContactsAction(String string) {
doSearch();
@@ -652,6 +657,8 @@
mListFragment.setSearchMode(mSearchMode);
mListFragment.setSearchResultsMode(mSearchResultsMode);
mListFragment.setQueryString(mInitialFilter);
+ mListFragment.setContactNameDisplayOrder(mContactsPrefs.getDisplayOrder());
+ mListFragment.setSortOrder(mContactsPrefs.getSortOrder());
if ((mMode & MODE_MASK_SHOW_PHOTOS) == MODE_MASK_SHOW_PHOTOS) {
mListFragment.setPhotoLoaderEnabled(true);
@@ -743,6 +750,12 @@
protected void onResume() {
super.onResume();
+ // Move to the fragment
+ if (mListFragment != null) {
+ mListFragment.setContactNameDisplayOrder(mContactsPrefs.getDisplayOrder());
+ mListFragment.setSortOrder(mContactsPrefs.getSortOrder());
+ }
+
// TODO move this to onAttach of the corresponding fragment
mListView = (ListView) findViewById(android.R.id.list);
@@ -1922,6 +1935,7 @@
if (mListFragment != null) {
mListFragment.setContactNameDisplayOrder(mDisplayOrder);
+ mListFragment.setSortOrder(mSortOrder);
}
if (mListView instanceof ContactEntryListView) {
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index 0fc025e..97c7a1c 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -18,7 +18,11 @@
import com.android.contacts.ContactsListActivity;
import com.android.contacts.R;
+import android.app.patterns.CursorLoader;
+import android.app.patterns.Loader;
+import android.database.Cursor;
import android.net.Uri;
+import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -33,6 +37,20 @@
private boolean mEditMode;
private boolean mCreateContactEnabled;
+ private CursorLoader mLoader;
+
+ @Override
+ protected CursorLoader onCreateLoader(int id, Bundle args) {
+ mLoader = new CursorLoader(getActivity(), null, null, null, null, null);
+ return mLoader;
+ }
+
+ @Override
+ protected void reloadData() {
+ getAdapter().configureLoader(mLoader);
+ mLoader.forceLoad();
+ }
+
public void setOnContactListActionListener(OnContactBrowserActionListener listener) {
mListener = listener;
}
@@ -42,6 +60,16 @@
}
@Override
+ protected void onInitializeLoaders() {
+ startLoading(0, null);
+ }
+
+ @Override
+ protected void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ getAdapter().changeCursor(data);
+ }
+
+ @Override
protected void onItemClick(int position, long id) {
if (isSearchAllContactsItemPosition(position)) {
mListener.onSearchAllContactsAction((String)null);
@@ -66,6 +94,13 @@
new ContactItemListAdapter((ContactsListActivity)getActivity());
adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
adapter.setDisplayPhotos(isPhotoLoaderEnabled());
+ adapter.setSearchMode(isSearchMode());
+ adapter.setSearchResultsMode(isSearchResultsMode());
+ adapter.setQueryString(getQueryString());
+ adapter.setContactNameDisplayOrder(getContactNameDisplayOrder());
+ adapter.setSortOrder(getSortOrder());
+
+ adapter.configureLoader(mLoader);
return adapter;
}
@@ -129,4 +164,5 @@
super.finish();
mListener.onFinishAction();
}
+
}
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index e5b9087..dbd6561 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -19,12 +19,16 @@
import com.android.contacts.widget.TextWithHighlighting;
import com.android.contacts.widget.TextWithHighlightingFactory;
+import android.app.patterns.CursorLoader;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.ContactCounts;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.SearchSnippetColumns;
+import android.text.TextUtils;
import android.widget.ListView;
/**
@@ -33,6 +37,39 @@
*/
public abstract class ContactEntryListAdapter extends PinnedHeaderListAdapter {
+ // TODO move to type-specific adapter
+ static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
+ Contacts._ID, // 0
+ Contacts.DISPLAY_NAME_PRIMARY, // 1
+ Contacts.DISPLAY_NAME_ALTERNATIVE, // 2
+ Contacts.SORT_KEY_PRIMARY, // 3
+ Contacts.STARRED, // 4
+ Contacts.TIMES_CONTACTED, // 5
+ Contacts.CONTACT_PRESENCE, // 6
+ Contacts.PHOTO_ID, // 7
+ Contacts.LOOKUP_KEY, // 8
+ Contacts.PHONETIC_NAME, // 9
+ Contacts.HAS_PHONE_NUMBER, // 10
+ };
+
+ // TODO move to type-specific adapter
+ static final String[] CONTACTS_SUMMARY_FILTER_PROJECTION = new String[] {
+ Contacts._ID, // 0
+ Contacts.DISPLAY_NAME_PRIMARY, // 1
+ Contacts.DISPLAY_NAME_ALTERNATIVE, // 2
+ Contacts.SORT_KEY_PRIMARY, // 3
+ Contacts.STARRED, // 4
+ Contacts.TIMES_CONTACTED, // 5
+ Contacts.CONTACT_PRESENCE, // 6
+ Contacts.PHOTO_ID, // 7
+ Contacts.LOOKUP_KEY, // 8
+ Contacts.PHONETIC_NAME, // 9
+ Contacts.HAS_PHONE_NUMBER, // 10
+ SearchSnippetColumns.SNIPPET_MIMETYPE, // 11
+ SearchSnippetColumns.SNIPPET_DATA1, // 12
+ SearchSnippetColumns.SNIPPET_DATA4, // 13
+ };
+
// TODO move to a type-specific adapter
public static final int SUMMARY_ID_COLUMN_INDEX = 0;
public static final int SUMMARY_DISPLAY_NAME_PRIMARY_COLUMN_INDEX = 1;
@@ -47,16 +84,39 @@
private TextWithHighlightingFactory mTextWithHighlightingFactory;
private int mDisplayOrder;
+ private int mSortOrder;
private boolean mNameHighlightingEnabled;
private ContactPhotoLoader mPhotoLoader;
+ private boolean mSectionHeaderDisplayEnabled;
- // TODO move to Loader
- protected String mQueryString;
+ private String mQueryString;
+ private boolean mSearchMode;
+ private boolean mSearchResultsMode;
public ContactEntryListAdapter(Context context) {
super(context);
}
+ public boolean isSearchMode() {
+ return mSearchMode;
+ }
+
+ public void setSearchMode(boolean flag) {
+ mSearchMode = flag;
+ }
+
+ public boolean isSearchResultsMode() {
+ return mSearchResultsMode;
+ }
+
+ public void setSearchResultsMode(boolean searchResultsMode) {
+ mSearchResultsMode = searchResultsMode;
+ }
+
+ public String getQueryString() {
+ return mQueryString;
+ }
+
public void setQueryString(String queryString) {
mQueryString = queryString;
}
@@ -65,14 +125,30 @@
return mContext;
}
- public void setContactNameDisplayOrder(int displayOrder) {
- mDisplayOrder = displayOrder;
+ public boolean isSectionHeaderDisplayEnabled() {
+ return mSectionHeaderDisplayEnabled;
+ }
+
+ public void setSectionHeaderDisplayEnabled(boolean flag) {
+ mSectionHeaderDisplayEnabled = flag;
}
public int getContactNameDisplayOrder() {
return mDisplayOrder;
}
+ public void setContactNameDisplayOrder(int displayOrder) {
+ mDisplayOrder = displayOrder;
+ }
+
+ public int getSortOrder() {
+ return mSortOrder;
+ }
+
+ public void setSortOrder(int sortOrder) {
+ mSortOrder = sortOrder;
+ }
+
public void setNameHighlightingEnabled(boolean flag) {
mNameHighlightingEnabled = flag;
}
@@ -97,6 +173,39 @@
return mPhotoLoader;
}
+ public void configureLoader(CursorLoader loader) {
+ Uri uri;
+ if (isSearchMode() || isSearchResultsMode()) {
+ String query = getQueryString();
+ uri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
+ TextUtils.isEmpty(query) ? "" : Uri.encode(query));
+ loader.setProjection(CONTACTS_SUMMARY_FILTER_PROJECTION);
+ if (!isSearchResultsMode()) {
+ loader.setSelection(Contacts.IN_VISIBLE_GROUP + "=1");
+ }
+ } else {
+ uri = Contacts.CONTENT_URI;
+ loader.setProjection(CONTACTS_SUMMARY_PROJECTION);
+ loader.setSelection(Contacts.IN_VISIBLE_GROUP + "=1");
+ }
+
+ if (isSectionHeaderDisplayEnabled()) {
+ uri = buildSectionIndexerUri(uri);
+ }
+
+ loader.setUri(uri);
+ if (mSortOrder == ContactsContract.Preferences.SORT_ORDER_PRIMARY) {
+ loader.setSortOrder(Contacts.SORT_KEY_PRIMARY);
+ } else {
+ loader.setSortOrder(Contacts.SORT_KEY_ALTERNATIVE);
+ }
+ }
+
+ private static Uri buildSectionIndexerUri(Uri uri) {
+ return uri.buildUpon()
+ .appendQueryParameter(ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, "true").build();
+ }
+
/*
* TODO change this method when loaders are introduced.
*/
@@ -109,7 +218,6 @@
public void moveToPosition(int position) {
// For side-effect
getItem(position);
- DatabaseUtils.dumpCurrentRow(getCursor());
}
public boolean getHasPhoneNumber() {
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index dfeb15e..aaa7f13 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -25,8 +25,10 @@
import com.android.contacts.widget.SearchEditText;
import com.android.contacts.widget.SearchEditText.OnCloseListener;
-import android.app.Fragment;
+import android.app.patterns.Loader;
+import android.app.patterns.LoaderManagingFragment;
import android.content.Context;
+import android.database.Cursor;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.Editable;
@@ -47,14 +49,15 @@
import android.widget.Filter;
import android.widget.ListView;
import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.OnItemClickListener;
+import android.widget.TextView.OnEditorActionListener;
/**
* Common base class for various contact-related list fragments.
*/
-public abstract class ContactEntryListFragment extends Fragment implements OnItemClickListener,
+public abstract class ContactEntryListFragment extends LoaderManagingFragment<Cursor>
+ implements OnItemClickListener,
OnScrollListener, TextWatcher, OnEditorActionListener, OnCloseListener,
OnFocusChangeListener, OnTouchListener {
@@ -77,10 +80,13 @@
private boolean mLegacyCompatibility;
private int mDisplayOrder;
+ private int mSortOrder;
+
private ContextMenuAdapter mContextMenuAdapter;
private ContactPhotoLoader mPhotoLoader;
private SearchEditText mSearchEditText;
+
protected abstract View inflateView(LayoutInflater inflater, ViewGroup container);
protected abstract ContactEntryListAdapter createListAdapter();
protected abstract void onItemClick(int position, long id);
@@ -89,6 +95,26 @@
return mAdapter;
}
+ // TODO make abstract
+ @Override
+ protected Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ throw new UnsupportedOperationException();
+ }
+
+ // TODO make abstract
+ @Override
+ protected void onInitializeLoaders() {
+ }
+
+ // TODO make abstract
+ @Override
+ protected void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ throw new UnsupportedOperationException();
+ }
+
+ protected void reloadData() {
+ }
+
/**
* Override to provide logic that dismisses this fragment.
*/
@@ -133,6 +159,9 @@
public void setQueryString(String queryString) {
mQueryString = queryString;
+ if (mAdapter != null) {
+ mAdapter.setQueryString(queryString);
+ }
}
public boolean isLegacyCompatibility() {
@@ -143,6 +172,10 @@
mLegacyCompatibility = flag;
}
+ public int getContactNameDisplayOrder() {
+ return mDisplayOrder;
+ }
+
public void setContactNameDisplayOrder(int displayOrder) {
mDisplayOrder = displayOrder;
if (mAdapter != null) {
@@ -150,6 +183,17 @@
}
}
+ public int getSortOrder() {
+ return mSortOrder;
+ }
+
+ public void setSortOrder(int sortOrder) {
+ mSortOrder = sortOrder;
+ if (mAdapter != null) {
+ mAdapter.setSortOrder(sortOrder);
+ }
+ }
+
@Deprecated
public void setContactsApplicationController(ContactsApplicationController controller) {
mAppController = controller;
@@ -208,8 +252,6 @@
mListView.setOnCreateContextMenuListener(mContextMenuAdapter);
}
- mAdapter.setContactNameDisplayOrder(mDisplayOrder);
-
configurePinnedHeader();
if (isPhotoLoaderEnabled()) {
@@ -225,7 +267,6 @@
mSearchEditText.addTextChangedListener(this);
mSearchEditText.setOnEditorActionListener(this);
mSearchEditText.setOnCloseListener(this);
- mAdapter.setQueryString(getQueryString());
}
if (isSearchResultsMode()) {
@@ -299,9 +340,7 @@
public void afterTextChanged(Editable s) {
String query = s.toString().trim();
setQueryString(query);
- mAdapter.setQueryString(query);
- Filter filter = mAdapter.getFilter();
- filter.filter(query);
+ reloadData();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
diff --git a/src/com/android/contacts/list/ContactItemListAdapter.java b/src/com/android/contacts/list/ContactItemListAdapter.java
index bd0efa3..35c0fb5 100644
--- a/src/com/android/contacts/list/ContactItemListAdapter.java
+++ b/src/com/android/contacts/list/ContactItemListAdapter.java
@@ -54,7 +54,6 @@
private boolean mDisplayCallButton = false;
protected boolean mDisplayAdditionalData = true;
private int mFrequentSeparatorPos = ListView.INVALID_POSITION;
- private boolean mSectionHeaderDisplayEnabled;
public ContactItemListAdapter(ContactsListActivity contactsListActivity) {
super(contactsListActivity);
@@ -82,14 +81,6 @@
}
}
- public void setSectionHeaderDisplayEnabled(boolean flag) {
- mSectionHeaderDisplayEnabled = flag;
- }
-
- public boolean isSectionHeaderDisplayEnabled() {
- return mSectionHeaderDisplayEnabled;
- }
-
public void setDisplayPhotos(boolean flag) {
mDisplayPhotos = flag;
}
@@ -101,7 +92,7 @@
*/
@Override
public void onContentChanged() {
- CharSequence constraint = mQueryString;
+ CharSequence constraint = getQueryString();
if (!TextUtils.isEmpty(constraint)) {
// Reset the filter state then start an async filter operation
Filter filter = getFilter();
@@ -123,7 +114,7 @@
}
if (contactsListActivity.mSearchMode) {
- return TextUtils.isEmpty(mQueryString);
+ return TextUtils.isEmpty(getQueryString());
} else if ((contactsListActivity.mMode & ContactsListActivity.MODE_MASK_CREATE_NEW) ==
ContactsListActivity.MODE_MASK_CREATE_NEW) {
// This mode mask adds a header and we always want it to show up, even
@@ -205,7 +196,7 @@
v = convertView;
}
bindView(v, getContext(), mCursor);
- bindSectionHeader(v, realPosition, mSectionHeaderDisplayEnabled);
+ bindSectionHeader(v, realPosition, isSectionHeaderDisplayEnabled());
return v;
}
@@ -219,7 +210,7 @@
int count = getRealCount();
if (contactsListActivity.mSearchMode
- && !TextUtils.isEmpty(mQueryString)) {
+ && !TextUtils.isEmpty(getQueryString())) {
text = contactsListActivity.getQuantityText(count, R.string.listFoundAllContactsZero,
R.plurals.searchFoundContacts);
} else {