【问题标题】:CursorLoader loading contacts - AndroidCursorLoader 加载联系人 - Android
【发布时间】:2015-04-22 12:08:29
【问题描述】:

我正在使用下面的代码,并加载联系人。一切都很好,当联系人大小小于 100 时。我使用选项卡,在哪里切换片段。当单击带有联系人的选项卡时,我得到了延迟。但我使用 CursorLoader,不明白为什么会有延迟。

使用该类加载联系人(ContactFetcher.fetchAll();)

更新!

有没有办法使用 LoaderManager 上传联系人,列出电话号码(如果联系人有多个)并列出电子邮件?举个例子就好了)

代码如下:

public class ContactFetcher {
    private Context context;

    public ContactFetcher(Context c) {
        this.context = c;
    }

    public ArrayList<MainContact> fetchAll() {
        ArrayList<MainContact> listContacts = new ArrayList<MainContact>();
        CursorLoader cursorLoader = new CursorLoader(context, RawContacts.CONTENT_URI,
                null, // the columns to retrieve (all)
                null, // the selection criteria (none)
                null, // the selection args (none)
                null // the sort order (default)
        );

        Cursor c = cursorLoader.loadInBackground();
        if (c.moveToFirst()) {
            do {
                MainContact contact = loadContactData(c);
                listContacts.add(contact);
            } while (c.moveToNext());
        }
        c.close();
        return listContacts;
    }

    private MainContact loadContactData(Cursor c) {
        // Get Contact ID
        int idIndex = c.getColumnIndex(ContactsContract.Contacts._ID);
        String contactId = c.getString(idIndex);
        // Get Contact Name
        int nameIndex = c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
        String contactDisplayName = c.getString(nameIndex);
        MainContact contact = new MainContact(contactId, contactDisplayName, null, null, null, true);
        fetchContactNumbers(c, contact);
        fetchContactEmails(c, contact);
        return contact;
    }

    public void fetchContactNumbers(Cursor cursor, MainContact contact) {
        // Get numbers
        final String[] numberProjection = new String[]{Phone.NUMBER, Phone.TYPE,};

        Cursor phone = new CursorLoader(context, Phone.CONTENT_URI, numberProjection,
                Phone.CONTACT_ID + " = ?", new String[]{String.valueOf(contact.id)}, null)
                .loadInBackground();

        if (phone.moveToFirst()) {
            final int contactNumberColumnIndex = phone.getColumnIndex(Phone.NUMBER);
            final int contactTypeColumnIndex = phone.getColumnIndex(Phone.TYPE);

            while (!phone.isAfterLast()) {
                final String number = phone.getString(contactNumberColumnIndex);
                final int type = phone.getInt(contactTypeColumnIndex);
                String customLabel = "Custom";
                CharSequence phoneType = Phone.getTypeLabel(
                        context.getResources(), type, customLabel);
                contact.addNumber(number, phoneType.toString());
                phone.moveToNext();
            }

        }
        phone.close();
    }

    public void fetchContactEmails(Cursor cursor, MainContact contact) {
        // Get email
        final String[] emailProjection = new String[]{Email.DATA, Email.TYPE};

        Cursor email = new CursorLoader(context, Email.CONTENT_URI, emailProjection,
                Email.CONTACT_ID + "= ?", new String[]{String.valueOf(contact.id)}, null)
                .loadInBackground();

        if (email.moveToFirst()) {
            final int contactEmailColumnIndex = email.getColumnIndex(Email.DATA);
            final int contactTypeColumnIndex = email.getColumnIndex(Email.TYPE);

            while (!email.isAfterLast()) {
                final String address = email.getString(contactEmailColumnIndex);
                final int type = email.getInt(contactTypeColumnIndex);
                String customLabel = "Custom";
                CharSequence emailType = Email.getTypeLabel(
                        context.getResources(), type, customLabel);
                contact.addEmail(address, emailType.toString());
                email.moveToNext();
            }

        }

        email.close();
    }
}

【问题讨论】:

  • 使用CursorAdapter,可能是移动光标列出耗时,您可以使用日志并查看打印时间来查找女巫操作耗时最多。
  • 更好的是只使用游标调用 loadContactData(c);在适配器的 getView 中。

标签: android database multithreading android-cursorloader


【解决方案1】:

问题是您没有正确使用CursorLoader。它不应该直接在诸如fetchContactNumbers() 的方法调用中创建或使用,这可能是从ActivityFragment 生命周期回调(如onResume())中调用的。相反,您应该使用LoaderManager.initLoader() 方法并提供一个实现LoaderManager.LoaderCallbacks 的类。在onCreateLoader() 回调中创建CursorLoader 并在onLoadFinished() 中检索结果。本文将帮助您了解Loader框架:http://po.st/xHoVMf

【讨论】:

  • 这是一个很好的例子,下载联系人?我认为,联系人会有问题,它有多个电话号码......
  • 这无关紧要 - 您可以在 onLoadFinished 中处理您需要的结果。现在你没有按预期使用加载器,所以它仍然在主线程上运行。
  • 任何人都可以使用 LoaderManager 修复我的代码,我不太了解光标工作)
  • @GenkaKasyan,您对Cursor 的调用不是问题,尽管您以后可能可以使用projection 和/或selection 来提高效率,从而改进您的搜索而不是返回所有记录。问题在于如何使用CursorLoader。看看我在答案中包含的文章,它有一个项目展示了如何使用CursorLoader。它检索通话记录而不是联系人,但概念完全相同。
  • @Saty 看起来链接缩短器这些天不起作用。在今天的 Android 中,您可能不想使用 Loader,因为它们很难正确处理,API 非常麻烦,而且使用其他架构组件(例如 LiveData)可以做得更干净。如果您仍然对有关 loader 的文章感兴趣,请看这里:hiqes.com/android-loaders
猜你喜欢
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
  • 1970-01-01
相关资源
最近更新 更多