草庐IT

Android 获取所有联系人列表(姓名、电子邮件、电话)需要超过一分钟的时间来获取大约 700 个联系人

coder 2023-11-19 原文

有什么办法可以缩短这个时间吗? 我用光标运行并获取姓名、电话号码和电子邮件

如果我从查询循环中删除电话号码查询,它将在 3 秒内结束

知道如何改进该查询吗?

也许我在查询中做错了什么?

(显然我正在异步执行,但仍然......用户等不及的时间很长)

希望有人可以分享他对此的看法

这是我的代码

ContentResolver cr = getContentResolver();
            Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
                    null, null, null, null);
            if (cur.getCount() > 0) {
                while (cur.moveToNext()) {
                    AddressBookEntity adr = new AddressBookEntity();
                    String id = cur.getString(cur
                            .getColumnIndex(ContactsContract.Contacts._ID));
                    String name = cur
                            .getString(cur
                                    .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                    adr.fullName = name;

                    Cursor emailCur = cr
                            .query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                                    null,
                                    ContactsContract.CommonDataKinds.Email.CONTACT_ID
                                            + " = ?", new String[] { id },
                                    null);
                    while (emailCur.moveToNext()) {
                        // This would allow you get several email addresses
                        // if the email addresses were stored in an array
                        String email = emailCur
                                .getString(emailCur
                                        .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                        if (!Utils.IsNullOrEmptyString(email)) {
                            adr.email = email;
                        }

                    }
                    emailCur.close();

                    if (Integer
                            .parseInt(cur.getString(cur
                                    .getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                        Cursor pCur = cr
                                .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                                        null,
                                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID
                                                + " = ?",
                                        new String[] { id }, null);
                        int phoneIndex = 0;
                        while (pCur.moveToNext()) {
                            String number = pCur.getString(pCur
                                    .getColumnIndex(Phone.NUMBER));

                            String country = Utils.GetCountryFromNumber(
                                    number, app);
                            number = Utils.GetFullPhoneNumber(number, app);
                            if (phoneIndex == 0) {
                                if (!Utils.IsNullOrEmptyString(number)) {
                                    adr.contactAdressBookId = id;
                                    adr.phoneNumber = number;
                                    adr.userInsertedId = app.userCred.userId;
                                    adr.country = country;
                                    myContacts.add(adr);
                                }
                            } else {
                                if (!Utils.IsNullOrEmptyString(number)) {
                                    AddressBookEntity adrMore = new AddressBookEntity();
                                    adrMore.fullName = adrMore.fullName;
                                    adrMore.country = adrMore.country;
                                    adrMore.email = adrMore.email;
                                    adrMore.phoneNumber = number;
                                    adrMore.contactAdressBookId = id;
                                    adrMore.country = country;
                                    myContacts.add(adrMore);
                                }
                            }
                        }
                        pCur.close();
                    }
                }
                cur.close();

最佳答案

使用以下 59 个联系人的代码,我在模拟器上得到了以下结果:

      D  ╔══════ query execution stats ═══════
      D  ║    got 59 contacts
      D  ║    query took 0.012 s (12 ms)
      D  ╚════════════════════════════════════

好的,那是最好的时间,但平均时间是 25-35 毫秒(对于 59 个联系人),在一些 onClick 回调中添加以下代码并运行几次以获得平均时间,在你的情况下你应该得到 30 * 700/59 = ~300-400 毫秒,而不是 3 秒,更不用说一分钟了 ;)

它使用设置为 API 级别 18 中添加的 Contactables.CONTENT_URI 的 Uri,但您可以在为 18 之前的 API 设备构建时使用 ContactsContract.Data.CONTENT_URI

List<AddressBookContact> list = new LinkedList<AddressBookContact>();
LongSparseArray<AddressBookContact> array = new LongSparseArray<AddressBookContact>();
long start = System.currentTimeMillis();

String[] projection = {
        ContactsContract.Data.MIMETYPE,
        ContactsContract.Data.CONTACT_ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Contactables.DATA,
        ContactsContract.CommonDataKinds.Contactables.TYPE,
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)";
String[] selectionArgs = {
        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;

Uri uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
// we could also use Uri uri = ContactsContract.Data.CONTENT_URI;

// ok, let's work...
Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);

final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA);
final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE);

while (cursor.moveToNext()) {
    long id = cursor.getLong(idIdx);
    AddressBookContact addressBookContact = array.get(id);
    if (addressBookContact == null) {
        addressBookContact = new AddressBookContact(id, cursor.getString(nameIdx), getResources());
        array.put(id, addressBookContact);
        list.add(addressBookContact);
    }
    int type = cursor.getInt(typeIdx);
    String data = cursor.getString(dataIdx);
    String mimeType = cursor.getString(mimeTypeIdx);
    if (mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
        // mimeType == ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
        addressBookContact.addEmail(type, data);
    } else {
        // mimeType == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
        addressBookContact.addPhone(type, data);
    }
}
long ms = System.currentTimeMillis() - start;
cursor.close();

// done!!! show the results...
int i = 1;
for (AddressBookContact addressBookContact : list) {
    Log.d(TAG, "AddressBookContact #" + i++ + ": " + addressBookContact.toString(true));
}
final String cOn = "<b><font color='#ff9900'>";
final String cOff = "</font></b>";
Spanned l1 = Html.fromHtml("got " + cOn + array.size() + cOff + " contacts<br/>");
Spanned l2 = Html.fromHtml("query took " + cOn + ms / 1000f + cOff + " s (" + cOn + ms + cOff + " ms)");

Log.d(TAG, "\n\n╔══════ query execution stats ═══════" );
Log.d(TAG, "║    " + l1);
Log.d(TAG, "║    " + l2);
Log.d(TAG, "╚════════════════════════════════════" );
SpannableStringBuilder msg = new SpannableStringBuilder().append(l1).append(l2);

LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
TextView tv = new TextView(this);
tv.setTextSize(20);
tv.setBackgroundColor(0xff000033);
tv.setPadding(24, 8, 24, 24);
tv.setText(msg);
ll.addView(tv);
ListView lv = new ListView(this);
lv.setAdapter(new ArrayAdapter<AddressBookContact>(this, android.R.layout.simple_list_item_1, list));
ll.addView(lv);
new AlertDialog.Builder(this).setView(ll).setPositiveButton("close", null).create().show();

帮助器 AddressBookContact 类:

class AddressBookContact {
    private long id;
    private Resources res;
    private String name;
    private LongSparseArray<String> emails;
    private LongSparseArray<String> phones;

    AddressBookContact(long id, String name, Resources res) {
        this.id = id;
        this.name = name;
        this.res = res;
    }

    @Override
    public String toString() {
        return toString(false);
    }

    public String toString(boolean rich) {
        SpannableStringBuilder builder = new SpannableStringBuilder();
        if (rich) {
            builder.append("id: ").append(Long.toString(id))
                    .append(", name: ").append("\u001b[1m").append(name).append("\u001b[0m");
        } else {
            builder.append(name);
        }

        if (phones != null) {
            builder.append("\n\tphones: ");
            for (int i = 0; i < phones.size(); i++) {
                int type = (int) phones.keyAt(i);
                builder.append(ContactsContract.CommonDataKinds.Phone.getTypeLabel(res, type, ""))
                        .append(": ")
                        .append(phones.valueAt(i));
                if (i + 1 < phones.size()) {
                    builder.append(", ");
                }
            }
        }

        if (emails != null) {
            builder.append("\n\temails: ");
            for (int i = 0; i < emails.size(); i++) {
                int type = (int) emails.keyAt(i);
                builder.append(ContactsContract.CommonDataKinds.Email.getTypeLabel(res, type, ""))
                        .append(": ")
                        .append(emails.valueAt(i));
                if (i + 1 < emails.size()) {
                    builder.append(", ");
                }
            }
        }
        return builder.toString();
    }

    public void addEmail(int type, String address) {
        if (emails == null) {
            emails = new LongSparseArray<String>();
        }
        emails.put(type, address);
    }

    public void addPhone(int type, String number) {
        if (phones == null) {
            phones = new LongSparseArray<String>();
        }
        phones.put(type, number);
    }
}

关于Android 获取所有联系人列表(姓名、电子邮件、电话)需要超过一分钟的时间来获取大约 700 个联系人,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26804387/

有关Android 获取所有联系人列表(姓名、电子邮件、电话)需要超过一分钟的时间来获取大约 700 个联系人的更多相关文章

  1. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  2. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  3. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  4. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  5. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  6. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  7. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  8. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  9. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  10. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

随机推荐