2

我正在尝试制作一个 AutoCompleteTextView 女巫将完成联系人列表中的用户输入,我做到了,但它造成了很大的性能损害。

我尝试使用 CursorLoader ( https://developer.android.com/training/load-data-background/setup-loader.html )

该应用程序现在强制关闭:

 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 

代码:

@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;
    }
}  

这是错误部分:

 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));
        }

错误是因为我将 Cursor 投射到 CursorLoader,我找不到另一种方法来做到这一点,因为我需要的方法在 CursorLoader 类型中不可用。

有没有人有办法解决吗?或另一种自动完成联系人而不损害性能的方法?谢谢!

4

2 回答 2

2

由于没有其他人提供答案,因此我建议在创建光标后在 onLoaderFinish 中填充您的数组。Cursor Loader 本质上是一个查询语句,而不是结果,这就是为什么不能从 CursorLoader 转换为 Cursor 的原因。

于 2013-08-26T15:46:00.537 回答
1

下面的代码是我用来AutoCompleteTextView在我的设备上填充所有电子邮件地址的代码。

它展示了如何使用LoaderCallbacks<Cursor>接口方法,并且基于 SDK 提供的模板 LoginActivity(在 Eclipse 中:File...New...Android Activity...Login)。


准备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;
}

请注意,这仅定义应加载的内容 - 它不会尝试填充任何数据结构。


处理结果:

/**
 * 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);
}

我不使用该onLoaderReset(Loader<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;
}
于 2014-10-08T10:23:20.517 回答