_StriveG Blog

别再无脑拷贝代码

前言

工作中发现,不少人喜欢无脑复制别人的代码,不管好坏。因此,写一篇博客记录下,干一行爱一行,不能仅仅是为了完成任务。

背景

在修改评论页面的时候发现,RecyclerView滑动巨卡,尤其是到了Emoji表情多的时候,很显然,是这里的问题。直接看下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void dealExpression(Context context,
SpannableString spannableString, Pattern patten, int start)
throws Exception {
Matcher matcher = patten.matcher(spannableString);
while (matcher.find()) {
String key = matcher.group();
if (matcher.start() < start) {
continue;
}
String value = emojiMap.get(key);
if (TextUtils.isEmpty(value)) {
continue;
}
// 通过上面匹配得到的字符串来生成图片资源id
int resId = context.getResources().getIdentifier(value, "drawable",
context.getPackageName());
if (resId != 0) {
Drawable emoji = context.getResources().getDrawable(resId);
int w = (int) (emoji.getIntrinsicWidth() * 0.40);
int h = (int) (emoji.getIntrinsicHeight() * 0.40);
emoji.setBounds(0, 0, w, h);
// 通过图片资源id来得到bitmap,用一个ImageSpan来包装
VerticalImageSpan imageSpan = new VerticalImageSpan(emoji);
// 计算该图片名字的长度,也就是要替换的字符串的长度
int end = matcher.start() + key.length();
// 将该图片替换字符串中规定的位置中
spannableString.setSpan(imageSpan, matcher.start(), end,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
if (end < spannableString.length()) {
dealExpression(context, spannableString, patten, end);
}
break;
}
}
}

解析部分代码如上,且不说其他相关连的low b代码,是在逗我么?正则匹配啥时候需要递归了。

方法名,复制粘贴,很快找到了,来源。来自这里

万恶的博客,虽然写博客是好事,但是博客真的害了不少人.

优化

我们要想优化上面的代码也很简单,从耗时处出发。

  1. 去掉递归,根本不需要
  2. 加速ImageSpan的生成过程

因此,我写下了如下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SpannableString getStrOpt(Context context) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
Resources resources = context.getResources();
SpannableString spanString = new SpannableString(text);
while (matcher.find()) {
String key = matcher.group();
EmojiImageSpan span = (EmojiImageSpan) mCache.get(key);
if (span == null) {
int value = emojiMap.get(key);
int id = resources.getIdentifier("icon"+value,"drawable",context.getPackageName());
Drawable drawable = resources.getDrawable(id);
drawable.setBounds(0,0,40,40);
span = new EmojiImageSpan(drawable);
mCache.put(key,span);
}else {
try {
span = span.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
spanString.setSpan(span,matcher.start(),matcher.start() + key.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
return spanString;
}

递归是完全不需要的,剩下的就是我们如何能快速生成ImageSpan。根据我们的知识,当然是cache了。这里选用LruCache,保证高频出现的emoji能快速提取出ImageSpan来。

虽然说上述的代码,在包含大量emoji的RecyclerView里面,极快速度滑动的情况下,还是有轻微的延迟,但是至少不会卡屏不动。

要想进一步优化,当然也是有方法的,我们可以选择延迟加载,大家一定都明白的。具体的做法这里就不说了。

总结

  • 不要轻易copy别人的代码
  • 做一个有追求的程序员

    最近访客