Android通讯录模糊匹配搜索实现(号码、首字母、简拼、全拼)


2013年12月10日 工作记录
小巫在工作中碰到一个需求,要求实现通讯录联系人的搜索,获取联系人的方式有好几种,我都有点混乱了,下面提供我最近用的一种,看起来还算比较简洁的,它是根据mimetypes表来查的。

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. // 查询所有联系人的姓名,电话,邮箱  
  2.   
  3. public ArrayList<Contact> loadContacts() throws Exception {  
  4.   
  5.     Uri uri = Uri.parse("content://com.android.contacts/contacts");  
  6.   
  7.     ContentResolver resolver = this.getContentResolver();  
  8.   
  9.     Cursor cursor = resolver.query(uri, new String[] { "_id" }, nullnull,  
  10.             null);  
  11.     ArrayList<Contact> contacts = new ArrayList<Contact>();  
  12.     while (cursor.moveToNext()) {  
  13.   
  14.         Contact contact = new Contact();  
  15.         int contractID = cursor.getInt(0);  
  16.   
  17.         StringBuilder sb = new StringBuilder("contractID=");  
  18.   
  19.         contact.setId(String.valueOf(contractID));  
  20.         sb.append(contractID);  
  21.   
  22.         uri = Uri.parse("content://com.android.contacts/contacts/"  
  23.                 + contractID + "/data");  
  24.   
  25.         Cursor cursor1 = resolver.query(uri, new String[] { "mimetype",  
  26.                 "data1""data2" }, nullnullnull);  
  27.   
  28.         while (cursor1.moveToNext()) {  
  29.   
  30.             String data1 = cursor1.getString(cursor1  
  31.                     .getColumnIndex("data1"));  
  32.   
  33.             String mimeType = cursor1.getString(cursor1  
  34.                     .getColumnIndex("mimetype"));  
  35.   
  36.             if ("vnd.android.cursor.item/name".equals(mimeType)) { // 是姓名  
  37.                 contact.setName(data1);  
  38.                 sb.append(",name=" + data1);  
  39.   
  40.             } else if ("vnd.android.cursor.item/email_v2".equals(mimeType)) { // 邮箱  
  41.                 if (!TextUtils.isEmpty(data1)) {  
  42.                     contact.setEmail(data1);  
  43.                 }  
  44.                 contacts.add(contact);  
  45.                 sb.append(",email=" + data1);  
  46.   
  47.             } else if ("vnd.android.cursor.item/phone_v2".equals(mimeType)) { // 手机  
  48.                 contact.setNumber(data1.replaceAll("-"""));  
  49.                 sb.append(",phone=" + data1);  
  50.             }  
  51.   
  52.         }  
  53.         contacts.add(contact);  
  54.         cursor1.close();  
  55.   
  56.         Log.i("wwj", sb.toString());  
  57.   
  58.     }  
  59.   
  60.     cursor.close();  
  61.     return contacts;  
  62.   
  63. }  




关于模糊匹配,我真的有点头大,我想到的是用正则表达式来做,但需要用到第三方类库pinyin4j.jar,我试了一下,效率都点低,明显感觉有点慢了,假如你的通讯录的量比较大,用这个来做确实不合时宜,或许可以进行优化的地方。


定义一个工具类
[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.search;  
  2.   
  3. import net.sourceforge.pinyin4j.PinyinHelper;  
  4. import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;  
  5. import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;  
  6. import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;  
  7. import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;  
  8. import android.provider.ContactsContract.CommonDataKinds.Phone;  
  9. import android.text.TextUtils;  
  10.   
  11. public class BaseUtil {  
  12.   
  13.     public final static String[] PHONES_PROJECTION = new String[] {  
  14.             Phone.DISPLAY_NAME, Phone.NUMBER };  
  15.   
  16.     public static String STRS[] = { """""[abc]""[def]""[ghi]""[jkl]",  
  17.             "[mno]""[pqrs]""[tuv]""[wxyz]" };  
  18.   
  19.     /** 
  20.      * 将字符串中的中文转化为拼音,其他字符不变 
  21.      *  
  22.      * @param inputString 
  23.      * @return 
  24.      */  
  25.     public static String getPingYin(String inputString) {  
  26.         if (TextUtils.isEmpty(inputString)) {  
  27.             return "";  
  28.         }  
  29.         HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();  
  30.         format.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
  31.         format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
  32.         format.setVCharType(HanyuPinyinVCharType.WITH_V);  
  33.   
  34.         char[] input = inputString.trim().toCharArray();  
  35.         String output = "";  
  36.   
  37.         try {  
  38.             for (int i = 0; i < input.length; i++) {  
  39.                 if (java.lang.Character.toString(input[i]).matches(  
  40.                         "[\\u4E00-\\u9FA5]+")) {  
  41.                     String[] temp = PinyinHelper.toHanyuPinyinStringArray(  
  42.                             input[i], format);  
  43.                     if (temp == null || TextUtils.isEmpty(temp[0])) {  
  44.                         continue;  
  45.                     }  
  46.                     output += temp[0].replaceFirst(temp[0].substring(01),  
  47.                             temp[0].substring(01).toUpperCase());  
  48.                 } else  
  49.                     output += java.lang.Character.toString(input[i]);  
  50.             }  
  51.         } catch (Exception e) {  
  52.             e.printStackTrace();  
  53.         }  
  54.         return output;  
  55.     }  
  56.   
  57. }  

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 按号码-拼音搜索联系人 
  3.  * @param str 
  4.  */  
  5. public void search(String str){  
  6.     contactList.clear();  
  7.     //如果搜索条件以0 1 +开头则按号码搜索  
  8.     if(str.toString().startsWith("0") || str.toString().startsWith("1")  
  9.              || str.toString().startsWith("+")){  
  10.         for(Model model : allContactList){  
  11.             if(model.telnum.contains(str)){  
  12.                 model.group = str;  
  13.                 contactList.add(model);  
  14.             }  
  15.         }  
  16.         adapter.refresh(contactList, false);  
  17.         return;  
  18.     }  
  19.     StringBuffer sb = new StringBuffer();  
  20.     //获取每一个数字对应的字母列表并以'-'隔开  
  21.     for(int i = 0; i < str.length(); i++){  
  22.         sb.append((str.charAt(i) <= '9' && str.charAt(i) >= '0')  
  23.                 ? BaseUtil.STRS[str.charAt(i) - '0'] : str.charAt(i));  
  24.         if(i != str.length() - 1){  
  25.             sb.append("-");  
  26.         }  
  27.     }  
  28.       
  29.     for(Model model : allContactList){  
  30.         if(contains(sb.toString(), model, str)){  
  31.             contactList.add(model);  
  32.         } else if(model.telnum.contains(str)){  
  33.             model.group = str;  
  34.             contactList.add(model);  
  35.         }  
  36.     }  
  37.     adapter.refresh(contactList, false);  
  38.    }  
  39.   
  40. /** 
  41.  * 根据拼音搜索 
  42.  * @param str           正则表达式 
  43.  * @param pyName        拼音 
  44.  * @param isIncludsive  搜索条件是否大于6个字符 
  45.  * @return 
  46.  */  
  47. public boolean contains(String str, Model model, String search){  
  48.     if(TextUtils.isEmpty(model.pyname)){  
  49.         return false;  
  50.     }  
  51.     model.group = "";  
  52.     //搜索条件大于6个字符将不按拼音首字母查询  
  53.     if(search.length() < 6){  
  54.         //根据首字母进行模糊查询  
  55.         Pattern pattern = Pattern.compile("^" + str.toUpperCase().replace("-""[*+#a-z]*"));  
  56.         Matcher matcher = pattern.matcher(model.pyname);  
  57.           
  58.         if(matcher.find()){  
  59.             String tempStr = matcher.group();  
  60.             for(int i = 0; i < tempStr.length(); i++){  
  61.                 if(tempStr.charAt(i) >= 'A' && tempStr.charAt(i) <= 'Z'){  
  62.                     model.group += tempStr.charAt(i);  
  63.                 }  
  64.             }  
  65.             return true;  
  66.         }  
  67.     }  
  68.       
  69.     //根据全拼查询  
  70.     Pattern pattern = Pattern.compile(str.replace("-"""), Pattern.CASE_INSENSITIVE);  
  71.     Matcher matcher = pattern.matcher(model.pyname);  
  72.     boolean flag = matcher.find();  
  73.     if(flag){  
  74.         model.group = matcher.group();  
  75.     }  
  76.     return flag;  
  77. }  

上面的代码是我从网上搜了很久才搜到的一个demo里面的代码,我整合到项目当中去,发现使用pinyin4j.jar类库效率实在有点低,所以我自己想了其他办法,不用第三方类库来实现。

下面是小巫的实现:

我找到一篇关于,中文字符转换为拼音的实现类,很有用
[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.suntek.mobilemeeting.utils;  
  2.   
  3. public class ChineseSpelling {  
  4.   
  5.     private static int[] pyvalue = new int[] { -20319, -20317, -20304, -20295,  
  6.             -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036,  
  7.             -20032, -20026, -20002, -19990, -19986, -19982, -19976, -19805,  
  8.             -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741,  
  9.             -19739, -19728, -19725, -19715, -19540, -19531, -19525, -19515,  
  10.             -19500, -19484, -19479, -19467, -19289, -19288, -19281, -19275,  
  11.             -19270, -19263, -19261, -19249, -19243, -19242, -19238, -19235,  
  12.             -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006,  
  13.             -19003, -18996, -18977, -18961, -18952, -18783, -18774, -18773,  
  14.             -18763, -18756, -18741, -18735, -18731, -18722, -18710, -18697,  
  15.             -18696, -18526, -18518, -18501, -18490, -18478, -18463, -18448,  
  16.             -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201,  
  17.             -18184, -18183, -18181, -18012, -17997, -17988, -17970, -17964,  
  18.             -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752,  
  19.             -17733, -17730, -17721, -17703, -17701, -17697, -17692, -17683,  
  20.             -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427,  
  21.             -17417, -17202, -17185, -16983, -16970, -16942, -16915, -16733,  
  22.             -16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470,  
  23.             -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423,  
  24.             -16419, -16412, -16407, -16403, -16401, -16393, -16220, -16216,  
  25.             -16212, -16205, -16202, -16187, -16180, -16171, -16169, -16158,  
  26.             -16155, -15959, -15958, -15944, -15933, -15920, -15915, -15903,  
  27.             -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659,  
  28.             -15652, -15640, -15631, -15625, -15454, -15448, -15436, -15435,  
  29.             -15419, -15416, -15408, -15394, -15385, -15377, -15375, -15369,  
  30.             -15363, -15362, -15183, -15180, -15165, -15158, -15153, -15150,  
  31.             -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121,  
  32.             -15119, -15117, -15110, -15109, -14941, -14937, -14933, -14930,  
  33.             -14929, -14928, -14926, -14922, -14921, -14914, -14908, -14902,  
  34.             -14894, -14889, -14882, -14873, -14871, -14857, -14678, -14674,  
  35.             -14670, -14668, -14663, -14654, -14645, -14630, -14594, -14429,  
  36.             -14407, -14399, -14384, -14379, -14368, -14355, -14353, -14345,  
  37.             -14170, -14159, -14151, -14149, -14145, -14140, -14137, -14135,  
  38.             -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094,  
  39.             -14092, -14090, -14087, -14083, -13917, -13914, -13910, -13907,  
  40.             -13906, -13905, -13896, -13894, -13878, -13870, -13859, -13847,  
  41.             -13831, -13658, -13611, -13601, -13406, -13404, -13400, -13398,  
  42.             -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343,  
  43.             -13340, -13329, -13326, -13318, -13147, -13138, -13120, -13107,  
  44.             -13096, -13095, -13091, -13076, -13068, -13063, -13060, -12888,  
  45.             -12875, -12871, -12860, -12858, -12852, -12849, -12838, -12831,  
  46.             -12829, -12812, -12802, -12607, -12597, -12594, -12585, -12556,  
  47.             -12359, -12346, -12320, -12300, -12120, -12099, -12089, -12074,  
  48.             -12067, -12058, -12039, -11867, -11861, -11847, -11831, -11798,  
  49.             -11781, -11604, -11589, -11536, -11358, -11340, -11339, -11324,  
  50.             -11303, -11097, -11077, -11067, -11055, -11052, -11045, -11041,  
  51.             -11038, -11024, -11020, -11019, -11018, -11014, -10838, -10832,  
  52.             -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533,  
  53.             -10519, -10331, -10329, -10328, -10322, -10315, -10309, -10307,  
  54.             -10296, -10281, -10274, -10270, -10262, -10260, -10256, -10254 };  
  55.   
  56.     private static String[] pystr = new String[] { "a""ai""an""ang",  
  57.             "ao""ba""bai""ban""bang""bao""bei""ben""beng",  
  58.             "bi""bian""biao""bie""bin""bing""bo""bu""ca",  
  59.             "cai""can""cang""cao""ce""ceng""cha""chai""chan",  
  60.             "chang""chao""che""chen""cheng""chi""chong""chou",  
  61.             "chu""chuai""chuan""chuang""chui""chun""chuo""ci",  
  62.             "cong""cou""cu""cuan""cui""cun""cuo""da""dai",  
  63.             "dan""dang""dao""de""deng""di""dian""diao""die",  
  64.             "ding""diu""dong""dou""du""duan""dui""dun""duo",  
  65.             "e""en""er""fa""fan""fang""fei""fen""feng""fo",  
  66.             "fou""fu""ga""gai""gan""gang""gao""ge""gei""gen",  
  67.             "geng""gong""gou""gu""gua""guai""guan""guang""gui",  
  68.             "gun""guo""ha""hai""han""hang""hao""he""hei",  
  69.             "hen""heng""hong""hou""hu""hua""huai""huan""huang",  
  70.             "hui""hun""huo""ji""jia""jian""jiang""jiao""jie",  
  71.             "jin""jing""jiong""jiu""ju""juan""jue""jun""ka",  
  72.             "kai""kan""kang""kao""ke""ken""keng""kong""kou",  
  73.             "ku""kua""kuai""kuan""kuang""kui""kun""kuo""la",  
  74.             "lai""lan""lang""lao""le""lei""leng""li""lia",  
  75.             "lian""liang""liao""lie""lin""ling""liu""long",  
  76.             "lou""lu""lv""luan""lue""lun""luo""ma""mai""man",  
  77.             "mang""mao""me""mei""men""meng""mi""mian""miao",  
  78.             "mie""min""ming""miu""mo""mou""mu""na""nai""nan",  
  79.             "nang""nao""ne""nei""nen""neng""ni""nian""niang",  
  80.             "niao""nie""nin""ning""niu""nong""nu""nv""nuan",  
  81.             "nue""nuo""o""ou""pa""pai""pan""pang""pao""pei",  
  82.             "pen""peng""pi""pian""piao""pie""pin""ping""po",  
  83.             "pu""qi""qia""qian""qiang""qiao""qie""qin""qing",  
  84.             "qiong""qiu""qu""quan""que""qun""ran""rang""rao",  
  85.             "re""ren""reng""ri""rong""rou""ru""ruan""rui",  
  86.             "run""ruo""sa""sai""san""sang""sao""se""sen",  
  87.             "seng""sha""shai""shan""shang""shao""she""shen",  
  88.             "sheng""shi""shou""shu""shua""shuai""shuan""shuang",  
  89.             "shui""shun""shuo""si""song""sou""su""suan""sui",  
  90.             "sun""suo""ta""tai""tan""tang""tao""te""teng",  
  91.             "ti""tian""tiao""tie""ting""tong""tou""tu""tuan",  
  92.             "tui""tun""tuo""wa""wai""wan""wang""wei""wen",  
  93.             "weng""wo""wu""xi""xia""xian""xiang""xiao""xie",  
  94.             "xin""xing""xiong""xiu""xu""xuan""xue""xun""ya",  
  95.             "yan""yang""yao""ye""yi""yin""ying""yo""yong",  
  96.             "you""yu""yuan""yue""yun""za""zai""zan""zang",  
  97.             "zao""ze""zei""zen""zeng""zha""zhai""zhan""zhang",  
  98.             "zhao""zhe""zhen""zheng""zhi""zhong""zhou""zhu",  
  99.             "zhua""zhuai""zhuan""zhuang""zhui""zhun""zhuo""zi",  
  100.             "zong""zou""zu""zuan""zui""zun""zuo" };  
  101.   
  102.     private StringBuilder buffer;  
  103.   
  104.     private String resource;  
  105.   
  106.     private static ChineseSpelling chineseSpelling = new ChineseSpelling();  
  107.   
  108.     public static ChineseSpelling getInstance() {  
  109.         return chineseSpelling;  
  110.     }  
  111.   
  112.     public String getResource() {  
  113.         return resource;  
  114.     }  
  115.   
  116.     public void setResource(String resource) {  
  117.         this.resource = resource;  
  118.     }  
  119.   
  120.     private int getChsAscii(String chs) {  
  121.         int asc = 0;  
  122.         try {  
  123.   
  124.             byte[] bytes = chs.getBytes("gb2312");  
  125.   
  126.             if (bytes == null || bytes.length > 2 || bytes.length <= 0) { // 错误  
  127.   
  128.                 // log  
  129.   
  130.                 throw new RuntimeException("illegal resource string");  
  131.                 // System.out.println("error");  
  132.   
  133.             }  
  134.             if (bytes.length == 1) { // 英文字符  
  135.   
  136.                 asc = bytes[0];  
  137.             }  
  138.             if (bytes.length == 2) { // 中文字符  
  139.   
  140.                 int hightByte = 256 + bytes[0];  
  141.                 int lowByte = 256 + bytes[1];  
  142.                 asc = (256 * hightByte + lowByte) - 256 * 256;  
  143.             }  
  144.         } catch (Exception e) {  
  145.             System.out  
  146.                     .println("ERROR:ChineseSpelling.class-getChsAscii(String chs)"  
  147.                             + e);  
  148.             // e.printStackTrace();  
  149.   
  150.         }  
  151.         return asc;  
  152.     }  
  153.   
  154.     public String convert(String str) {  
  155.         String result = null;  
  156.         int ascii = getChsAscii(str);  
  157.         // System.out.println(ascii);  
  158.   
  159.         if (ascii > 0 && ascii < 160) {  
  160.             result = String.valueOf((char) ascii);  
  161.         } else {  
  162.             for (int i = (pyvalue.length - 1); i >= 0; i--) {  
  163.                 if (pyvalue[i] <= ascii) {  
  164.                     result = pystr[i];  
  165.                     break;  
  166.                 }  
  167.             }  
  168.         }  
  169.         return result;  
  170.     }  
  171.   
  172.     public String getSelling(String chs) {  
  173.         String key, value;  
  174.         buffer = new StringBuilder();  
  175.         for (int i = 0; i < chs.length(); i++) {  
  176.             key = chs.substring(i, i + 1);  
  177.             if (key.getBytes().length >= 2) {  
  178.                 value = (String) convert(key);  
  179.                 if (value == null) {  
  180.                     value = "unknown";  
  181.                 }  
  182.             } else {  
  183.                 value = key;  
  184.             }  
  185.   
  186.             buffer.append(value);  
  187.         }  
  188.         return buffer.toString();  
  189.     }  
  190.   
  191.     public String getSpelling() {  
  192.         return this.getSelling(this.getResource());  
  193.     }  
  194. }  

不过我也发现了一问题,关于一个中文字符的字节数的问题,不同的编码可能会存在中文的字节数不同的情况,比如GBK编码的中文是2,而UTF-8的编码是3。其实我发现这个问题也挺惊奇的,这个问题可能是我们以后编码的时候会遇到的,一个编码就可能把你搞死。

英文字母:

字节数 : 1;编码:GB2312

字节数 : 1;编码:GBK

字节数 : 1;编码:GB18030

字节数 : 1;编码:ISO-8859-1

字节数 : 1;编码:UTF-8

字节数 : 4;编码:UTF-16

字节数 : 2;编码:UTF-16BE

字节数 : 2;编码:UTF-16LE

 

中文汉字:

字节数 : 2;编码:GB2312

字节数 : 2;编码:GBK

字节数 : 2;编码:GB18030

字节数 : 1;编码:ISO-8859-1

字节数 : 3;编码:UTF-8

字节数 : 4;编码:UTF-16

字节数 : 2;编码:UTF-16BE

字节数 : 2;编码:UTF-16LE

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 按号码-拼音搜索联系人 
  3.      *  
  4.      * @param str 
  5.      */  
  6.     public void search(String str) {  
  7.         contactList.clear();  
  8.         // 如果搜索条件以0 1 +开头则按号码搜索  
  9.         if (str.startsWith("0") || str.startsWith("1") || str.startsWith("+")) {  
  10.             for (Contact contact : allContacts) {  
  11.                 if (contact.getNumber().contains(str)) {  
  12.                     contact.setGroup(str);  
  13.                     contactList.add(contact);  
  14.                 }  
  15.             }  
  16.             refreshList();  
  17.             return;  
  18.         }  
  19.   
  20.         boolean isChinese = false;  
  21.         Pattern pattern = Pattern.compile("[\\u4E00-\\u9FA5]");  
  22.         Matcher matcher = pattern.matcher(str);  
  23.         if (matcher.find()) { // 如果是中文  
  24.             isChinese = true;  
  25.         }  
  26.   
  27.         for (Contact contact : allContacts) {  
  28.             if (contains(contact, str, isChinese)) {  
  29.                 contactList.add(contact);  
  30.             } else if (contact.getNumber().contains(str)) {  
  31.                 contact.setGroup(str);  
  32.                 contactList.add(contact);  
  33.             }  
  34.   
  35.         }  
  36.         refreshList();  
  37.     }  
  38.   
  39.     /** 
  40.      * 根据拼音搜索 
  41.      *  
  42.      * @param str 
  43.      *            正则表达式 
  44.      * @param pyName 
  45.      *            拼音 
  46.      * @param isIncludsive 
  47.      *            搜索条件是否大于6个字符 
  48.      * @return 
  49.      */  
  50.     public boolean contains(Contact contact, String search, boolean isChinese) {  
  51.         if (TextUtils.isEmpty(contact.getName())) {  
  52.             return false;  
  53.         }  
  54.   
  55.         boolean flag = false;  
  56.         if (isChinese) {  
  57.             // 根据全拼中文查询  
  58.             Pattern pattern = Pattern.compile(search.replace("-"""),  
  59.                     Pattern.CASE_INSENSITIVE);  
  60.             Matcher matcher = pattern.matcher(contact.getName());  
  61.             if (flag) {  
  62.                 contact.setGroup(matcher.group());  
  63.             }  
  64.             return matcher.find();  
  65.         }  
  66.   
  67.         // 简拼匹配  
  68.         ChineseSpelling finder = ChineseSpelling.getInstance();  
  69.         finder.setResource(contact.getName());  
  70.         Pattern pattern2 = Pattern.compile(search.toUpperCase(),  
  71.                 Pattern.CASE_INSENSITIVE);  
  72.         Matcher matcher2 = pattern2.matcher(finder.getSpelling());  
  73.         flag = matcher2.find();  
  74.   
  75.         return flag;  
  76.     }  

我发现自己换了这种方法之后,速度一下子提升了很多,满足了自己的需求,用第三方类库虽好,但涉及到用户体验这一块,你不得不低头,小巫总结在此,这篇博客我相信总会有人需要的,如果有帮助到你,不要忘记好评哈,你的支持将是我无限的动力。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值