Reputation: 54
I'm trying to make an AutoCompleteTextView witch will complete user input from the contacts list, I made it but it caused a big preformence damage.
I tried to use CursorLoader (https://developer.android.com/training/load-data-background/setup-loader.html)
the app is now force closing:
07-30 05:02:45.034: E/AndroidRuntime(1396): FATAL EXCEPTION: main
07-30 05:02:45.034: E/AndroidRuntime(1396): java.lang.ClassCastException:
android.content.CursorLoader cannot be cast to android.database.Cursor
CODE:
@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle)
{
/*
* Takes action based on the ID of the Loader that's being created
*/
switch (loaderID) {
case NAMES_LOADER:
// Returns a new CursorLoader
CursorLoader peopleCursor = new CursorLoader(
context, // Parent activity context
ContactsContract.Contacts.CONTENT_URI, // Table to query
null, // Projection to return
null, // No selection clause
null, // No selection arguments
null // Default sort order
);
while (((Cursor) peopleCursor).moveToNext()) {
contactName = ((Cursor) peopleCursor).getString(((Cursor) peopleCursor)
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
contactId = ((Cursor) peopleCursor).getString(((Cursor) peopleCursor)
.getColumnIndex(ContactsContract.Contacts._ID));
hasPhone = ((Cursor) peopleCursor)
.getString(((Cursor) peopleCursor)
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
}
case PHONES_LOADER:
if ((Integer.parseInt(hasPhone) > 0)){
CursorLoader phonesCursor = new CursorLoader(
context, // Parent activity context
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, // Table to query
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, // Projection to return
null, // No selection clause
null // No selection arguments
// Default sort order
);
while (((Cursor) phonesCursor).moveToNext()){
//store numbers and display a dialog letting the user select which.
String phoneNumber = ((Cursor) phonesCursor).getString(
((Cursor) phonesCursor).getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Map<String, String> NamePhoneType = new ContactMap();
NamePhoneType.put("Name", contactName);
NamePhoneType.put("Phone", phoneNumber);
mPeopleList.add(NamePhoneType);
}
}
default:
// An invalid id was passed in
return null;
}
}
this is the error part:
while (((Cursor) peopleCursor).moveToNext()) {
contactName = ((Cursor) peopleCursor).getString(((Cursor) peopleCursor)
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
contactId = ((Cursor) peopleCursor).getString(((Cursor) peopleCursor)
.getColumnIndex(ContactsContract.Contacts._ID));
hasPhone = ((Cursor) peopleCursor)
.getString(((Cursor) peopleCursor)
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
}
the error is because I'm casting Cursor to CursorLoader, I cant find another way to do it because the methhoodes I need are not avalible in the type CursorLoader.
does anyone have a solution? or another way to auto complete contacts without damaging preformence? thanks!
Upvotes: 2
Views: 524
Reputation: 29722
The below code is what I use to populate my AutoCompleteTextView
with all email addresses on my device.
It shows how to use the LoaderCallbacks<Cursor>
interface methods, and is based on the template LoginActivity supplied by the SDK (in Eclipse: File...New... Android Activity... Login).
Preparing the CursorLoader
:
/**
* Creates a new {@link CursorLoader} that reads email addresses from the device contact list.
*/
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle)
{
/* URI for the device profile contact only - not used in this activity */
@SuppressWarnings("unused")
Uri uriDeviceProfileContact =
Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
/* URI for all contacts on the device */
Uri uriAllContacts = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
CursorLoader profileLoader =
new CursorLoader(this, uriAllContacts, ProfileQuery.PROJECTION,
ContactsContract.Contacts.Data.MIMETYPE + " = ?", new String[]
{ ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE },
ContactsContract.CommonDataKinds.Email.ADDRESS);
return profileLoader;
}
Note that this only defines what should be loaded - it does not attempt to populate any data structures.
Process results:
/**
* Adds loaded email addresses to the autocomplete field.
*/
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor)
{
List<String> emails = new ArrayList<String>();
cursor.moveToFirst();
while (!cursor.isAfterLast())
{
emails.add(cursor.getString(ProfileQuery.ADDRESS));
cursor.moveToNext();
}
addEmailsToAutoComplete(emails);
}
private void addEmailsToAutoComplete(List<String> emailAddressCollection)
{
// Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(InterviewMethodTest.this,
android.R.layout.simple_dropdown_item_1line, emailAddressCollection);
myAutoCompleteField.setAdapter(adapter);
}
I do not make use of the onLoaderReset(Loader<Cursor>)
method.
The above code requires the following projection of the data to the cursor:
/**
* Defines the mappings used to get the email addresses from the contact list.
*/
private interface ProfileQuery
{
/** Columns to fetch from the database into the cursor. */
String[] PROJECTION =
{ ContactsContract.CommonDataKinds.Email.ADDRESS,
ContactsContract.CommonDataKinds.Email.IS_PRIMARY, };
/** Column in cursor of the address. */
int ADDRESS = 0;
/** Column in cursor of the primary email address indicator. */
@SuppressWarnings("unused")
int IS_PRIMARY = 1;
}
Upvotes: 1
Reputation: 76
Since no one else has offered an answer, let me suggest populating your array in onLoaderFinish after the cursor has been created. The Cursor Loader is essentially a query statement and not the results, which is why you can't cast from a CursorLoader to a Cursor.
Upvotes: 2