拨号盘搜索联系人数据库更新分析 --- 之二

1.2 insertNamePrefixes

DialerDatabaseHelper的insertNamePrefixes方法调用流程图如下,


insertNamePrefixes方法主要逻辑如下,

1,从smartdial_table表单中获取联系人的姓名和id,

final int columnIndexName = nameCursor.getColumnIndex(
     SmartDialDbColumns.DISPLAY_NAME_PRIMARY);
final int columnIndexContactId = 
nameCursor.getColumnIndex(SmartDialDbColumns.CONTACT_ID);

2,构造prefix_table表单插入语句

final String sqlInsert = "INSERT INTO " + Tables.PREFIX_TABLE + " (" +
•••
final SQLiteStatement insert = db.compileStatement(sqlInsert);

3,逐条插入,首先调用SmartDialPrefix的generateNamePrefixes方法将姓名转化为对应的数字,

然后将数字和id利用插入语句插入prefix_table表单

while (nameCursor.moveToNext()) {
      /** Computes a list of prefixes of a given contact name. */
   final ArrayList<String> namePrefixes =
SmartDialPrefix.generateNamePrefixes(nameCursor.getString(columnIndexName));
for (String namePrefix : namePrefixes) {
        insert.bindLong(1, nameCursor.getLong(columnIndexContactId));
        insert.bindString(2, namePrefix);
        insert.executeInsert();
        insert.clearBindings();
   }
}

SmartDialPrefix的generateNamePrefixes方法主要逻辑如下,

1,调用parseToIndexTokens方法将姓名转化为数字字符组,

final ArrayList<String> indexTokens = parseToIndexTokens(index);

如果姓名都是由字母和数字组成,则indexTokens 只有一个字符串;否则一般由其他字符(空格)返回的是多个字符串。例如 zhangmanxue 返回的是 一个字符 94264626983, zhang man xue 中间有2个空格,返回三个字符,分别是94264,626,983.

2,将返回的数字字符组

final StringBuilder fullNameToken = new StringBuilder();
for (int i = indexTokens.size() - 1; i >= 0; i--) {
    fullNameToken.insert(0, indexTokens.get(i));
    result.add(fullNameToken.toString());
}

还是上面的例子,如果是zhangmanxue,则result中的数字字符组依次为983, 626983, 94264626983.

ArrayList<String> fullNames = Lists.newArrayList();
//获取indexTokens中最后一个数字串字符 为983
fullNames.add(indexTokens.get(indexTokens.size() - 1));
final int recursiveNameStart = result.size();// 3
int recursiveNameEnd = result.size();// 3

下面接着按照示例来,

for (int i = indexTokens.size() - 2; i >= 0; i--) {
   if ((i >= indexTokens.size() - LAST_TOKENS_FOR_INITIALS) ||
        (i < FIRST_TOKENS_FOR_INITIALS)) {

LAST_TOKENS_FOR_INITIALS和 FIRST_TOKENS_FOR_INITIALS的值都为2,

因此,这个if判断最多正确3次,倒数第一个元素和顺数第一个和第二个元素。

按照示例,正确2次,第一次如下,

initial = indexTokens.get(i).substring(0, 1); //626 中的6
/** Recursively adds initial combinations to the list.*/
for (int j = 0; j < fullNames.size(); ++j) {
   result.add(initial + fullNames.get(j));//添加6983
}
for (int j = recursiveNameStart; j < recursiveNameEnd; ++j) {
    result.add(initial + result.get(j));//不执行 recursiveNameStart和recursiveNameEnd 都是3
 }
recursiveNameEnd = result.size();// 4
final String currentFullName = fullNames.get(fullNames.size() - 1);// 为983
fullNames.add(indexTokens.get(i) +  currentFullName);//添加626983

此时result 中有4个值,依次是983, 626983, 94264626983, 6983

当i为0时,第二次循环如下,

initial = indexTokens.get(i).substring(0, 1); //94264中的9
/** Recursively adds initial combinations to the list.*/
// 循环2次,依次添加 9983,9626983
for (int j = 0; j < fullNames.size(); ++j) {
   result.add(initial + fullNames.get(j));
}
for (int j = recursiveNameStart; j < recursiveNameEnd; ++j) {
    result.add(initial + result.get(j));//执行一次,添加96983
 }
recursiveNameEnd = result.size();
final String currentFullName = fullNames.get(fullNames.size() - 1);
fullNames.add(indexTokens.get(i) +  currentFullName);

因此,最后result中一共有7个值,分别是983, 626983, 94264626983, 6983, 9983,9626983, 96983.prefix_table表单对应如下,


对于其他姓名,也可以对照分析。

parseToIndexTokens方法主要逻辑如下,

对每个姓名字符串进行操作,

for (int i = 0; i < length; i++) {

for循环里面的逻辑如下,

此时的mMap对象是LatinSmartDialMap对象.

如果是a到z的字母或者0到9的字符,则调用LatinSmartDialMap的getDialpadIndex方法进行转化,

if (mMap.isValidDialpadCharacter(c)) {
   /** Converts a character into the number on dialpad that represents the character.*/
  currentIndexToken.append(mMap.getDialpadIndex(c));
}

否则就添加到result中,在此从头开始进行检测,

if (currentIndexToken.length() != 0) {
    result.add(currentIndexToken.toString());
}
currentIndexToken.delete(0, currentIndexToken.length());

也就是说,如果联系人姓名中有不是a到z的字母或者0到9的字符,就会进行拆分, 例如,ngmanxue 返回的是 一个字符 94264626983, zhang man xue 中间有2个空格,返回三个字符,分别是94264,626,983.

LatinSmartDialMap的getDialpadIndex方法逻辑如下,

1,如果是0到9的字符,就转化为0到9的数字;

2,如果是a到z的字母,则按照LATIN_LETTERS_TO_DIGITS的映射关系转化为0到9的字符,然后就转化为0到9的数字;

if (ch >= '0' && ch <= '9') {
     return (byte) (ch - '0');
} else if (ch >= 'a' && ch <= 'z') {
     return (byte) (LATIN_LETTERS_TO_DIGITS[ch - 'a'] - '0');
} else {
    return -1;
}

LATIN_LETTERS_TO_DIGITS变量如下,

private static final char[] LATIN_LETTERS_TO_DIGITS = {
  '2', '2', '2', // A,B,C -> 2
  '3', '3', '3', // D,E,F -> 3
  '4', '4', '4', // G,H,I -> 4
   '5', '5', '5', // J,K,L -> 5
   '6', '6', '6', // M,N,O -> 6
   '7', '7', '7', '7', // P,Q,R,S -> 7
   '8', '8', '8', // T,U,V -> 8
   '9', '9', '9', '9' // W,X,Y,Z -> 9
};

很巧妙的使用了字符相减的方法进行对应。因此, A,B,C映射为2, D,E,F映射为3, G,H,I映射为4, J,K,L映射为5, M,N,O映射为6, P,Q,R,S映射为7, T,U,V映射为8, W,X,Y,Z映射为9.

因此, dialer.db 数据库终于更新和映射完成了,进行匹配查询的时候可以不用查询contacts2.db数据库,直接查询dialer.db 数据库就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值