Регулярное выражение SpannableString в ListView

#android #regex #spannablestring

#Android #регулярное выражение #spannablestring

Вопрос:

У меня есть ListView, к которому я привязываю коллекцию строк, используя пользовательский адаптер. Я также подчеркиваю определенные ключевые слова в тексте. Я использую SpannableString и регулярное выражение для подчеркивания слов, но мне интересно, является ли это наиболее эффективным способом сделать это? Я замечаю много распределений в трекере распределения java.util.regex.Сопоставитель и классы regex.util.regex.Pattern, которые могут вызывать утечки памяти в моем приложении. Я знаю, что регулярные выражения могут быть дорогими, но я не уверен, что есть другой способ сделать то, что мне нужно.

     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;
    }
}
  

Ответ №1:

Вы создаете множество шаблонов и сопоставлений, которые вам не нужны. Я предлагаю вам создать одно регулярное выражение, соответствующее всем ключевым словам, например:

 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;
}
  

Создание объектов шаблонов довольно дорого, так что именно здесь вы получите реальную экономию. С другой стороны, сопоставители относительно дешевы, поэтому я перешел от использования статического экземпляра к созданию нового каждый раз.

Комментарии:

1. Спасибо, я проверю это позже и дам вам знать.

2. Просто внедрил этот код, и он отлично сработал. Уменьшено много моих выделений. Большое спасибо!