Improve scrolling on group member picker
Bug 28707265
Bug 18641067
Change-Id: I9f939c0ba804c1a0482b589126bb57dcb80d7fdf
diff --git a/src/com/android/contacts/list/GroupMemberPickListAdapter.java b/src/com/android/contacts/list/GroupMemberPickListAdapter.java
index 7a1d355..ae6517c 100644
--- a/src/com/android/contacts/list/GroupMemberPickListAdapter.java
+++ b/src/com/android/contacts/list/GroupMemberPickListAdapter.java
@@ -102,14 +102,12 @@
@Override
public void configureLoader(CursorLoader loader, long directoryId) {
loader.setUri(RawContacts.CONTENT_URI);
-
loader.setProjection(
getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
? GroupMembersQuery.PROJECTION_PRIMARY
: GroupMembersQuery.PROJECTION_ALTERNATIVE);
loader.setSelection(getSelection());
loader.setSelectionArgs(getSelectionArgs());
-
loader.setSortOrder(getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY
? Data.SORT_KEY_PRIMARY : Data.SORT_KEY_ALTERNATIVE
+ " COLLATE LOCALIZED ASC");
diff --git a/src/com/android/contacts/list/GroupMemberPickerFragment.java b/src/com/android/contacts/list/GroupMemberPickerFragment.java
index ae82b21..d965e21 100644
--- a/src/com/android/contacts/list/GroupMemberPickerFragment.java
+++ b/src/com/android/contacts/list/GroupMemberPickerFragment.java
@@ -15,16 +15,16 @@
*/
package com.android.contacts.list;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.net.Uri;
import android.os.Bundle;
-import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.RawContacts;
+import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
@@ -46,12 +46,16 @@
public class GroupMemberPickerFragment extends
ContactEntryListFragment<GroupMemberPickListAdapter> {
+ public static final String TAG = "GroupMemberPicker";
+
private static final String KEY_ACCOUNT = "account";
private static final String KEY_RAW_CONTACT_IDS = "rawContactIds";
private static final String ARG_ACCOUNT = "account";
private static final String ARG_RAW_CONTACT_IDS = "rawContactIds";
+ private static final int LOADER_CONTACT_ENTITY = 0;
+
/** Callbacks for host of {@link GroupMemberPickerFragment}. */
public interface Listener {
@@ -74,16 +78,30 @@
mCount = super.getCount();
mIndex = new int[mCount];
+
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "FilterCursorWrapper starting size cursor=" + mCount + " photosMap="
+ + (mContactPhotosMap == null ? 0 : mContactPhotosMap.size()));
+ }
+
for (int i = 0; i < mCount; i++) {
super.moveToPosition(i);
final String rawContactId = getString(GroupMembersQuery.RAW_CONTACT_ID);
if (!mRawContactIds.contains(rawContactId)) {
mIndex[mPos++] = i;
+ } else if (mContactPhotosMap != null) {
+ final long contactId = getLong(GroupMembersQuery.CONTACT_ID);
+ mContactPhotosMap.remove(contactId);
}
}
mCount = mPos;
mPos = 0;
super.moveToFirst();
+
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "FilterCursorWrapper ending size cursor=" + mCount + " photosMap="
+ + (mContactPhotosMap == null ? 0 : mContactPhotosMap.size()));
+ }
}
@Override
@@ -151,6 +169,11 @@
return super.getLong(columnIndex);
}
+ private Pair<Long,String> getContactPhotoPair(long contactId) {
+ return mContactPhotosMap != null && mContactPhotosMap.containsKey(contactId)
+ ? mContactPhotosMap.get(contactId) : null;
+ }
+
@Override
public boolean move(int offset) {
return moveToPosition(mPos + offset);
@@ -193,9 +216,41 @@
}
}
+ private final LoaderCallbacks<Cursor> mContactsEntityCallbacks = new LoaderCallbacks<Cursor>() {
+
+ private final String[] PROJECTION = new String[] {
+ Contacts._ID,
+ Contacts.PHOTO_ID,
+ Contacts.LOOKUP_KEY
+ };
+
+ @Override
+ public CursorLoader onCreateLoader(int id, Bundle args) {
+ final CursorLoader loader = new CursorLoader(getActivity());
+ loader.setUri(Contacts.CONTENT_URI);
+ loader.setProjection(PROJECTION);
+ return loader;
+ }
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ mContactPhotosMap = new HashMap<>();
+ while (cursor.moveToNext()) {
+ final long contactId = cursor.getLong(0);
+ final Pair<Long, String> pair =
+ new Pair(cursor.getLong(1), cursor.getString(2));
+ mContactPhotosMap.put(contactId, pair);
+ }
+ GroupMemberPickerFragment.super.startLoading();
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {}
+ };
+
private AccountWithDataSet mAccount;
private ArrayList<String> mRawContactIds;
- private Map<Long, Pair<Long,String>> mContactPhotoMap = new HashMap();
+ // Contact ID longs to Pairs of photo ID and contact lookup keys
+ private Map<Long, Pair<Long,String>> mContactPhotosMap;
private Listener mListener;
@@ -213,6 +268,7 @@
public GroupMemberPickerFragment() {
setQuickContactEnabled(false);
setPhotoLoaderEnabled(true);
+ setVisibleScrollbarEnabled(true);
setHasOptionsMenu(true);
}
@@ -235,6 +291,15 @@
outState.putStringArrayList(KEY_RAW_CONTACT_IDS, mRawContactIds);
}
+ @Override
+ protected void startLoading() {
+ if (mContactPhotosMap == null) {
+ getLoaderManager().restartLoader(LOADER_CONTACT_ENTITY, null, mContactsEntityCallbacks);
+ } else {
+ super.startLoading();
+ }
+ }
+
public void setListener(Listener listener) {
mListener = listener;
}
@@ -261,6 +326,7 @@
super.configureAdapter();
getAdapter().setAccount(mAccount);
getAdapter().setRawContactIds(mRawContactIds);
+ getAdapter().setEmptyListEnabled(true);
}
@Override
@@ -269,31 +335,4 @@
mListener.onGroupMemberClicked(getAdapter().getRawContactUri(position));
}
}
-
- // TODO(wjang): unacceptable scrolling performance for big groups
- private Pair<Long,String> getContactPhotoPair(long contactId) {
- if (mContactPhotoMap.containsKey(contactId)) {
- return mContactPhotoMap.get(contactId);
- }
- final Uri uri = Data.CONTENT_URI.buildUpon()
- .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
- String.valueOf(Directory.DEFAULT))
- .build();
- final String[] projection = new String[] { Data.PHOTO_ID, Data.LOOKUP_KEY };
- final String selection = Data.CONTACT_ID + "=?";
- final String[] selectionArgs = new String[] { Long.toString(contactId) };
- Cursor cursor = null;
- try {
- cursor = getActivity().getContentResolver().query(
- uri, projection, selection, selectionArgs, /* sortOrder */ null);
- if (cursor != null && cursor.moveToFirst()) {
- final Pair<Long, String> pair = new Pair(cursor.getLong(0), cursor.getString(1));
- mContactPhotoMap.put(contactId, pair);
- return pair;
- }
- } finally {
- if (cursor != null) cursor.close();
- }
- return null;
- }
}