2014-10-22 83 views
0

我想做一個列表視圖有TextView元素,其中每個包含一個SpannableString。這些TextView的內容從Html標記中的ArrayList中獲取,並使用Html.fromHtml轉換爲SpannableStrings。現在,Html.fromHtml有很多性能問題。於是,我就使Html.fromHtmlHtml.fromHtml的替代軟件?

class NeoHTML extends DefaultHandler { 

SpannableStringBuilder s; 
String html; 
Context context; 

public NeoHTML(String html,Context context) { 
    s = new SpannableStringBuilder(""); 
    this.html = html; 
    this.context=context; 
    getXml(); 
} 

public SpannableStringBuilder fromHTML() { 
    return s; 
} 


public void getXml() { 
    try { 

     SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); 
     SAXParser saxParser = saxParserFactory.newSAXParser(); 
     DefaultHandler defaultHandler = new DefaultHandler() { 

      int boldTag = 0; 
      int italicsTag = 0; 
      int underlineTag = 0; 
      int pointer = 0; 
      boolean brpassed=false; 
      public void startElement(String uri, String localName, 
        String qName, Attributes attributes) 
        throws SAXException { 

       if (qName.equalsIgnoreCase("B")) { 
        boldTag += 1; 
       } 
       if (qName.equalsIgnoreCase("I")) { 
        italicsTag += 1; 
       } 
       if (qName.equalsIgnoreCase("U")) { 
        underlineTag += 1; 
       } 
      } 

      public void characters(char ch[], int start, int length) 
        throws SAXException { 
       int tstart=start; 


        if(new String(ch, start, length).startsWith("[ ]")){ 
         s.append("b"); 
         Typeface font = Typeface.createFromAsset(context.getAssets(), "tickfont.ttf"); 
         s.setSpan (new CustomTypefaceSpan("", font),pointer, pointer+1,Spanned.SPAN_EXCLUSIVE_INCLUSIVE); 
         pointer+=1; 
         tstart+=3; 
        } 

        else if(new String(ch, start, length).startsWith("[*]")){ 
         s.append("a"); 
         Typeface font = Typeface.createFromAsset(context.getAssets(), "tickfont.ttf"); 
         s.setSpan (new CustomTypefaceSpan("", font),pointer, pointer+1,Spanned.SPAN_EXCLUSIVE_INCLUSIVE); 
         pointer+=1; 
         tstart+=3; 
        } 



       if (boldTag > 0 || italicsTag > 0 || underlineTag > 0) { 
        s.append(new String(ch, tstart, length)); 
        if (boldTag > 0) { 

         s.setSpan(new StyleSpan(
           android.graphics.Typeface.BOLD), pointer, 
           pointer + length, 
           Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 

        } 
        if (italicsTag > 0) { 

         s.setSpan(new StyleSpan(
           android.graphics.Typeface.ITALIC), pointer, 
           pointer + length, 
           Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 

        } 
        if (underlineTag > 0) { 

         s.setSpan(new UnderlineSpan(), pointer, pointer 
           + length, 
           Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
        } 

       } else { 
        s.append(new String(ch, tstart, length)); 
       } 

       pointer += length; 
      } 

      public void endElement(String uri, String localName, 
        String qName) throws SAXException { 

       if (qName.equalsIgnoreCase("B")) { 
        boldTag -= 1; 
       } 
       if (qName.equalsIgnoreCase("BR")) { 
        s.append("\n"); 
        pointer+=1; 
        brpassed=true; 
       } 
       if (qName.equalsIgnoreCase("I")) { 
        italicsTag -= 1; 
       } 
       if (qName.equalsIgnoreCase("U")) { 
        underlineTag -= 1; 
       } 
      } 
     }; 
     saxParser.parse(new InputSource(new StringReader(html)), 
       defaultHandler); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

}我自己的版本

這是一個簡單的基於SAX解析器。我的靈感來自CommonsWare Is there a faster way to decode html characters to a string than Html.fromHtml()?的回答。它具有最小的功能(粗體,斜體,下劃線和中斷)但即便如此,性能並沒有得到改善。我有一些想法,比如將textview合成爲位圖並將其緩存在內存中,而不必在listview回收時再次將其重新渲染。任何人都可以提出任何想法..(請避免NDK爲基礎的解決方案,因爲我從來沒有成功編譯任何它們,它增加了不必要的複雜性)

+0

試圖使用「低級」拉解析器? – pskink 2014-10-22 08:31:34

+0

@pskink,我不希望它太複雜。這是一個小問題。添加NDK不是一種選擇。抱歉。 但你能建議一個好的低級解析器嗎? – avinayak 2014-10-22 08:38:51

+0

複雜?你的意思是簡單嗎?請參閱:http://pastebin.com/6yU3tGaR – pskink 2014-10-22 09:06:29

回答

2

我有一個類似的問題,而當我做了Html.fromHtml文本是模糊的某些設備上時必須大膽。所以這是我的解決方案:

public static Spannable boldFromHtml(Context c, String text, boolean extraBold){ 
    String textTemp = text; 

    int boldStartPos = 0; 
    int boldEndPos = 1; 
    List<int[]> spanList = new LinkedList<int[]>(); 

    while((boldStartPos = textTemp.indexOf("<b>", boldStartPos)) != -1 && (boldEndPos = textTemp.indexOf("</b>", boldStartPos) - 3) != -1){ 
     textTemp = textTemp.replaceFirst("<b>", "").replaceFirst("</b>", ""); 
     spanList.add(new int[]{boldStartPos, boldEndPos}); 
     boldStartPos += 3; 
    } 

    Spannable span = new SpannableString(textTemp); 
    for(int[] selection: spanList){ 
     span.setSpan(new BoldTypefaceSpan("sans-serif", (extraBold) ? MyExtraBoldFont(c) : MyBoldFont(c)), selection[0], selection[1], Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
    } 

    return span; 
} 

此功能只粗體顯示您的元素,但它可以很容易地修改爲執行其他標記。

+0

這與我的嘗試類似。我不認爲這會提高性能 – avinayak 2014-10-22 08:39:58