ListView中的SpannableString正则表达式 [英] SpannableString regex in a ListView
问题描述
我有一个ListView,我正在使用自定义适配器将一组字符串绑定到其中.我还在文本中强调某些关键字.我正在使用SpannableString和正则表达式对单词加下划线,但是我想知道这是否是最有效的方法?我注意到java.util.regex.Matcher和regex.util.regex.Pattern类的Allocation Tracker中有很多分配,这可能会导致我的应用程序发生内存泄漏.我知道正则表达式可能会很昂贵,但是我不确定另一种做我需要做的方法.
I have a ListView that I'm binding a collection of strings to, using a custom adapter. I'm also underlining certain keywords in the text. I'm using a SpannableString and a regular expression to underline the words, but I'm wondering if this is the most efficient way to do it? I'm noticing a lot of allocations in the Allocation Tracker of the java.util.regex.Matcher and the regex.util.regex.Pattern classes, which may be causing memory leaks in my app. I know regex's can be expensive, but I'm not sure another way to do what I need to do.
public class Main extends ListActivity
{
private static CustomAdapter adapter = null;
private static List<Keyword> keywords;
private static Matcher matcher;
@Override
public void onCreate(Bundle icicle)
{
List<Item> items = new ArrayList<Item>();
keywords = GetKeywords();
items = GetItems();
adapter = new CustomAdapter();
for (Item item : items)
adapter.addItem(item);
this.setListAdapter(adapter);
adapter.notifyDataSetChanged();
}
/* ADAPTER */
private class CustomAdapter extends BaseAdapter
{
private final List<Item> mData = new ArrayList<Item>();
private final LayoutInflater mInflater;
public CustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(Item item) {
mData.add(item);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
final Item item = (Item)this.getItem(position);
if (convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.main, parent, false);
holder.text = (TextView)convertView.findViewById(R.id.text);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
holder.text.setText(Highlight(item.getTitle(), keywords, matcher), BufferType.SPANNABLE);
return(convertView);
}
}
static class ViewHolder {
TextView text, date, site;
}
private SpannableString Highlight(String text, List<Keyword> keywords, Matcher matcher)
{
final SpannableString content = new SpannableString(text);
for (Keyword keyword : keywords)
{
matcher = Pattern.compile("\\b" + keyword + "\\b").matcher(text);
if (matcher.find())
{
start = matcher.start();
end = matcher.end();
content.setSpan(new UnderlineSpan(), start, end, 0);
}
}
}
return content;
}
}
推荐答案
您正在创建许多不需要的模式和匹配器.建议您创建一个正则表达式以匹配所有关键字,例如:
You are creating a lot of Patterns and Matchers you don't need. I suggest you create one regex to match all the keywords, like this:
private SpannableString Highlight(String text, List<Keyword> keywords)
{
final SpannableString content = new SpannableString(text);
if (keywords.size() > 0)
{
/* create a regex of the form: \b(?:word1|word2|word3)\b */
StringBuilder sb = ne StringBuilder("\\b(?:").append(keywords.get(0).toString());
for (int i = 1; i < keywords.size(); i++)
{
sb.append("|").append(keywords.get(i).toString());
}
sb.append(")\\b");
Matcher m = Pattern.compile(sb.toString()).matcher(text);
while (m.find())
{
content.setSpan(new UnderlineSpan(), m.start(), m.end(), 0);
}
}
return content;
}
模式对象的创建非常昂贵,因此真正的节省将来自此.另一方面,Matchers相对便宜,这就是为什么我从使用静态实例切换为每次创建一个新实例的原因.
Pattern objects are quite expensive to create, so that's where your real savings will come from. On the other hand, Matchers are relatively cheap, which is why I switched from using a static instance to creating a new one each time.
这篇关于ListView中的SpannableString正则表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!