关于短信第一次进入慢的问题分析

问题是这样的,测试机器中,单个联系人(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循环。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值