项目中的android 车机系统 搜索联系人算法一直有问题 , 这里就把整个的流程写一遍

 

一 . 搜索算法实现的功能

1.支持中文,英文搜索

2.支持电话号码搜索

3.支持汉语拼音搜索, 首字母搜索也能支持, 同时对检索到的文字显示高亮

前面的第一, 第二点, 都是比较简单的, 通过遍历字符串, 查看字符串是否包含用户输入的字符, 就能达到检索的功能

重点是第三点,拼音的搜索,首字母搜索

 

二. 拼音搜索的流程

1.先介绍几个类

ContactData.java , 里面保存有手机端同步过来的数据
public class ContactData implements Serializable, Parcelable {    public static final int CONTACT_NAME_MAX_LENGTH = 16;    public static final int CONTACT_PHONE_MAX_LENGTH = 32;    private String name = "";    private String letter = "";    private List phoneNumTypeList = new ArrayList<>();    private List phoneNumList = new ArrayList<>();    public List numbers = new ArrayList<>();    private List addressList = new ArrayList<>();    public int photoType;    public byte[] photoBytes;     ....  //一些可能用到的方法}
SearchResult.java  , 搜索结果实体类 . 
public class SearchResult implements Serializable, Cloneable, Parcelable {    private static final long serialVersionUID = -8624630249543035384L;    public long contactID = -1;    public String name = "";    public String phone;    public String time;    public int count = 1;    // 加入优先级 排序用的    int priority = -1;    public String pinyin;    public String number;    public String initials;    public String pinyinInitials;    // 高亮    public String[] highlight;    // 分解    ArrayList nodes;    public int photoType;    public byte[] photoBytes;    ...// 一些可能使用到的方法}

Pinyin.java 这个类来自于开源的项目 com.github.promeg.pinyinhelper , 通过下面的语句,可以将中文转化为拼音, 具体的原理, 不详,有时间再看看

            // 汉字            String pinyin = Pinyin.toPinyin(c);

 

 

2.实现流程, 

a.先将同步到的联系人数据contacts 转为searchResult 数据,  这个过程就是将名字数据转换为拼音,  生成首字母数据pinyinInitials 

    private List convertFormatSearchResult(List contactsList) {        Lg.i(TAG, " convertFormatSearchResult ");        if (contactsList == null || contactsList.isEmpty()) {            return Lists.newArrayList();        }        List searchResults = new ArrayList<>();        String phoneNumber;        String name;        String tempKey = null;        for (ContactData phones : contactsList) {            int size = phones.numbers.size();            for (int i = 0; i < size; i++) {                name = phones.getName();                phoneNumber = phones.numbers.get(i).number;                SearchResult phoneContact = new SearchResult();                phoneContact.name = name;                phoneContact.phone = phoneNumber;                // 分字                phoneContact.formatPinYin();                String pinyinInitials = PinyinUtils.cn2FirstSpell(name, false);                String pinyin = PinyinUtils.cn2Spell(name, false, true, true, "");                String initialsNumber = PinyinUtils.pinyinConvertToNumber(pinyinInitials);                String pinyinNumber = PinyinUtils.pinyinConvertToNumber(pinyin);                // 取得名字所有字母转化为拼音                phoneContact.pinyin = pinyin;                // 取首字母 并 转换为 数字                phoneContact.initials = initialsNumber;                phoneContact.pinyinInitials = pinyinInitials;                // 取所有字母 并 转化为 数字                phoneContact.number = pinyinNumber;                phoneContact.photoType = phones.photoType;                phoneContact.photoBytes = phones.photoBytes;                searchResults.add(phoneContact);            }        }        return searchResults;    }

b. 建立循环, 遍历所有的已知searchResult ,    查看与检索项匹配的联系人, 添加到 result 中

    public static List searchContactByAll(final List source, final String query) {        List result = new ArrayList<>();        // 汉语转拼音        String pyInput = PinyinUtils.cn2Spell(query, false, true, true, "");        String pyInitialInput = PinyinUtils.cn2FirstSpell(query, false);        for (SearchResult user : source) {            // 重置高亮            user.resetAllHighlight();            // 标识是否包含搜索内容            boolean flag = false;            // 搜索内容 不能大于 联系人拼音的长度            // 搜索中文的时候, 我们直接遍历名字            if (pyInput.length() <= user.pinyin.length()) {                if(StringUtils.checkChinese(query)){                    if (user.name.contains(query)) {                        user.priority = 1;                        if(user.name.startsWith(query)) {                            // 优先级为最大                            user.priority = 0;                        }                        //由于名字中可能含有多音字,所以使用name.indexof                        int j = user.name.indexOf(query);                        //避免这里出现数组越界                        for (int i = 0; i < user.nodes.size() - j; i++) {                            // 设置高亮                            updateHighlight(user.nodes.get(j + i), -1);                        }                        result.add(user);                    }                    continue;                }                if (StringUtils.checkChinese(user.name)) {                    if (user.name.contains(query)) {                        user.priority = 1;                        if(user.name.startsWith(query)) {                            // 优先级为最大                            user.priority = 0;                        }                        //由于名字中可能含有多音字,所以使用name.indexof                        int j = user.name.indexOf(query);                        //避免这里出现数组越界                        for (int i = 0; i < user.nodes.size() - j; i++) {                            // 设置高亮                            updateHighlight(user.nodes.get(j + i), -1);                        }                        flag = true;                    } else if (user.pinyin.toLowerCase().startsWith(pyInput.toLowerCase())) {// 直接拼音匹配                        // 优先级为1                        user.priority = 2;                        //避免这里出现数组越界                        for (int i = 0; i < user.nodes.size(); i++) {                            updateHighlight(user.nodes.get(i), -1);                        }                        flag = true;                    } else {                        // 深层拷贝ArrayList                        ArrayList nodes = Lists.newArrayList();                        for (PyNode pyNode : user.nodes) {                            try {                                PyNode node = (PyNode) pyNode.clone();                                node.number = node.pinyin; // 注意这里换掉T9算法中的number,使用拼音代替!                                nodes.add(node);                            } catch (CloneNotSupportedException e) {                                e.printStackTrace();                            }                        }                        // 全部转换为小写                        pyInput = pyInput.toLowerCase(Locale.getDefault());                        // 开启递归搜索                        flag = pinyinRecursion(pyInput, 0, 1, 0, nodes, false);                        // 优先级                        user.priority = user.getNodeHighlightString().indexOf("1") + 400;                    }                } else {                    // 英文                    String name = user.pinyin.toLowerCase(Locale.getDefault());                    String key = query.toLowerCase(Locale.getDefault());                    if (name.contains(key)) {                        int length = key.length(), j = name.indexOf(key);                        // 优先级                        user.priority = j + 1200;                        if(name.startsWith(key)) {                            user.priority = j + 800;                        }                        // 设置高亮                        StringBuilder sb = new StringBuilder();                        for (int i = 0; i < length; i++) {                            sb.append(1);                        }                        StringBuilder highlight = new StringBuilder(user.highlight[0]);                        highlight.replace(j, length + j, sb.toString());                        user.highlight[0] = highlight.toString();                        flag = true;                    }                }            }            // 搜索电话            if (!flag && user.phone.contains(query)) {                if(user.phone.equals(query)) {                    user.priority = 9997;                } else if(user.phone.startsWith(query)) {                    user.priority = 9998;                } else {                    user.priority = 9999 + user.phone.indexOf(query);                }                // 重置高亮                user.resetAllHighlight();                flag = true;            }            // 判断是否匹配成功            if (flag) {                result.add(user);            }        }        Collections.sort(result, new ListComparator());        return result;    }

 

3.总结 :

主要工作就是两点, 一是把名字转化为拼音, 二是找到匹配的联系人项, 并标注匹配的字串

 

之前一直有个问题,

1. 不支持中文全拼检索 , 发现是已经检索到,只是数组越界了, 

 2. 中文会被先转为拼音,然后检索.   这个也是不对的,  正确的做法是中文检索优先级最高

 

 

 

 

更多相关文章

  1. 同样line-height下ios和Android显示不一致的问题
  2. android/NDK开发assets资源中文名打包问题
  3. Linux Kernel and Android(安卓)休眠与唤醒(中文版)
  4. android JNI C代码对sdcard中文件的操作
  5. Android(安卓)权限中文说明
  6. RxJava RxAndroid(安卓)资源收录
  7. Android(安卓)Studio 3.1.2 新项目报错 AAPT2 error: check logs
  8. Android(安卓)Studio 2.0 正式版发布啦 (首次中文翻译)
  9. Android(安卓)四大组件之一 :BroadCastReceiver 广播接收器详解

随机推荐

  1. widget(1、TextView)
  2. Android进度条源代码
  3. Dialog窗口形式的Activity
  4. android广播监听短信并显示内容
  5. ScrollView中嵌入ListView办法
  6. Android 滚动字幕ScrollTextView
  7. Customize Android Fonts
  8. android 无线调试
  9. android 5.0UI特效
  10. android 获取网络类型名称2G 3G 4G wifi