问题是这样的,测试机器中,单个联系人(10068)有180条短信记录,然后每次点击进入延迟2-5秒钟。
在测试人员提供的日志中分析得出,activity显示出来耗时800ms,而list列表显示数据消耗4秒:
01-09 16:53:57.280 844 891 I ActivityManager: Displayed com.android.mms/.ui.ComposeMessageActivity: +991ms
01-09 16:54:01.012 21147 21147 D Mms/MessageItemCache: bindView():type=sms, msgId=2250
在这段时间内,日志中显示有大量的打印短信中的URl:
01-09 16:53:57.410 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
01-09 16:53:57.412 21147 21147 D DefaultPatterns: getWebUrl, return: gd.10086.cn/app30
01-09 16:53:57.415 21147 10634 D MessagingNotification: getUndeliveredMessageCount
01-09 16:53:57.420 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
01-09 16:53:57.429 21147 21147 D DefaultPatterns: getWebUrl, return: gd.10086.cn/app30
01-09 16:53:57.444 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
01-09 16:53:57.456 21147 21147 D DefaultPatterns: getWebUrl, return: gd.10086.cn/app06
01-09 16:53:57.477 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
01-09 16:53:57.484 21147 21147 D DefaultPatterns: getWebUrl, return: gd.10086.cn/app30
01-09 16:53:57.511 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
01-09 16:53:57.530 21147 21147 D DefaultPatterns: getWebUrl, return: gd.10086.cn/cxll
01-09 16:53:57.555 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
01-09 16:53:57.574 21147 21147 D DefaultPatterns: getWebUrl, return: gd.10086.cn/cxll
01-09 16:53:57.598 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
01-09 16:53:57.603 21147 21147 D DefaultWebProtocolNames: getWebProtocolNames
所以这里可以排除adapter没有使用缓存机制。
在AsyncQueryHandler的onQueryComplete方法中有一个异常方法:
/// M: Code analyze 047, Extra uri from message body and get number from uri.
/// Then use this number to update contact cache. @{
if (mNeedUpdateContactForMessageContent) {
updateContactCache(cursor);
mNeedUpdateContactForMessageContent = false;
}
而updateContactCache(cursor);的具体实现如下:
/// M: Code analyze 047, Extra uri from message body and get number from uri.
/// Then use this number to update contact cache. @{
private void updateContactCache(Cursor cursor) {
if (cursor != null) {
Set<SpannableString> msgs = new HashSet<SpannableString>();
while (cursor.moveToNext()) {
String smsBody = cursor.getString(MessageListAdapter.COLUMN_SMS_BODY);
if (smsBody == null) {
continue;
}
SpannableString msg = new SpannableString(smsBody);
msgs.add(msg);
}
// update the contact cache in an async thread to avoid ANR
updateContactCacheAsync(msgs);
}
}
private void updateContactCacheAsync(final Set<SpannableString> msgs) {
for (SpannableString msg : msgs) {
Linkify.addLinks(msg, Linkify.ALL);
}
new Thread(new Runnable() {
public void run() {
Set<String> uriSet = new HashSet<String>();
for (SpannableString msg : msgs) {
List<String> uris = MessageUtils.extractUris(msg.getSpans(0, msg.length(),
URLSpan.class));
for (String uri : uris) {
uriSet.add(uri);
}
}
for (String uri : uriSet) {
String[] body = uri.toLowerCase().split("tel:");
if (body.length > 1) {
Contact.get(body[1].trim(), false);
}
}
}
}).start();
}
/// @}
updateContactCacheAsync方法中,原作者使用了4个for循环,而且for循环在子线程之外。所以这个就导致了主线程缓慢的原因。
优化方法如下:
private void updateContactCacheAsync(final Set<SpannableString> msgs) {
/*for (SpannableString msg : msgs) {
Linkify.addLinks(msg, Linkify.ALL);
}*/
new Thread(new Runnable() {
public void run() {
//Set<String> uriSet = new HashSet<String>();
for (SpannableString msg : msgs) {
Linkify.addLinks(msg, Linkify.PHONE_NUMBERS);
List<String> uris = MessageUtils.extractUris(msg.getSpans(0, msg.length(),
URLSpan.class));
for (String uri : uris) {
//uriSet.add(uri);
String[] body = uri.toLowerCase().split("tel:");
if (body.length > 1) {
Contact.get(body[1].trim(), false);
}
}
}
/*for (String uri : uriSet) {
String[] body = uri.toLowerCase().split("tel:");
if (body.length > 1) {
Contact.get(body[1].trim(), false);
}
}*/
}
}).start();
}
/// @}
1.将外部for循环放入到里面;
2.将提取连接的操作放到第一个循环中:Linkify.addLinks(msg, Linkify.PHONE_NUMBERS);
3.将判断电话号码连接操作放到第二层for循环。