【问题标题】:Android Contacts Search: Using dialpad keys (alphabets combinations/permutations)Android 联系人搜索:使用拨号盘键(字母组合/排列)
【发布时间】:2019-09-09 09:32:01
【问题描述】:

我正在尝试构建一个 Android 拨号器应用程序 (MinSDK 23)。

我想实现联系人搜索(通常在默认拨号器应用和其他第三方拨号器应用中可用),如下所示:

当我在拨号盘上键入数字时,例如245

我应该能够搜索电话号码包含“245”的联系人以及他们的姓名包含与数字 245 的字母组合匹配的联系人,根据我的计算,这应该是 27 个唯一组合。

虽然我知道这是一个排列问题,并且我可以通过在联系人姓名上应用 OR 'LIKE' 过滤器来进行搜索,但这似乎不够有效,并且在我不断输入时会导致更多性能问题,例如245658.

我们如何有效地做到这一点?是否有任何内置搜索机制可以通过这种方式搜索 android 联系人,或者是否存在更好的自定义解决方案?

【问题讨论】:

    标签: android search android-contacts android-dialer


    【解决方案1】:

    这是我们公司的经典面试题。

    首先,不要为输入的每个数字都点击 ContactsContract API,您需要在启动期间运行单个查询以从 Contacts DB 中获取所有名称,这样您就可以在其中快速搜索它们记忆。

    类似:

    Map<String, Long> namesMap = new HashMap<>();
    String[] projection = new String[]{Contacts._ID, Contacts.DISPLAY_NAME};
    Cursor c = getContentResolver().query(Contacts.CONTENT_URI, projection, null, null, null);
    while (c != null && c.moveToNext()) {
        namesMap.put(c.getString(1), c.getLong(0));
    }
    c.close();
    

    接下来,过滤上述NamesMap 以仅获取适合搜索数字的名称的最佳方法是生成正则表达式模式。

    因此,245 的搜索查询将生成正则表达式:.*[2abc][4ghi][5jkl].*,构建起来应该不会太难,每个数字都映射到固定字符串:2 -> [2abc]

    准备好正则表达式模式后,您将遍历namesMap 并仅返回键与模式匹配的条目。 确保在构建 namesMap 时进行不区分大小写的匹配,或者改为小写所有名称。

    【讨论】:

    • 那么我们假设有多少联系人可以安全地加载到内存中?每次启动拨号器活动时执行的操作是否足够快?人们倾向于打开拨号器并期望立即拨入号码。如果我使用一些数据库,那么它会打开一个全新的 Pandora 盒子,在每次启动时同步联系人。
    • 如果你只加载联系人姓名,我认为这里没有问题,你可以加载任意数量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 2014-03-30
    • 2014-11-01
    • 1970-01-01
    • 2018-01-05
    相关资源
    最近更新 更多