2011-10-21 10 views
2

独自の構文ハイライターを作成する必要があると判断しました。これまでのところ動作していますが、リアルタイムで(ハイライト表示)、遅いです。構文ハイライダーの最適化

どのように動作するか説明しようとします。ユーザーがEditTextに何かを入力するたびに、(TextWatcherを介して)ハイライターを実行します。ハイライターは、単語の先頭を見つけるまでテキストを検索し、同じ単語の終わりを見つけるまで検索します。単語を見つけたら、一連のキーワードを検索し、一致するものがあればその場所にスパナブルを設定します。ドキュメントの終わりに達するまで繰り返しループします。

もう一度、この方法を続ける前にこのアイデアを試してみてください。しかし、それは遅いです。いくつかの行をいくつかの行を通過するために何度かそれを取ることができます。 EditTextにテキストがどのくらい速く表示されるかが遅くなります。 - また、ユーザーが入力した最後の位置にテキストが入力された後で、ハイライターがどこで始まるかを設定しました。毎回全体の文書を調べなければならないので、多少は役に立ちます。

public class CodeView extends EditText { 
    private int mTxtChangeStart; 
    String mStructures[] = this.getResources().getStringArray(R.array.structures); 

    public CodeView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     addTextChangedListener(inputTextWatcher); 

       ... 
     } 

    TextWatcher inputTextWatcher = new TextWatcher() { 

     @Override 
     public void afterTextChanged(Editable s) { 
      syntaxHighlight(); 
     } 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, 
       int after) { 
      //Set where we should start highlighting 
      mTxtChangeStart = start; 
     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, 
       int count) { 


     } 

    }; 

    private void syntaxHighlight() { 

     //Time how long it takes for debugging 
     long syntime = System.currentTimeMillis(); 
     Log.d("", "Start Syntax Highlight"); 


     //Get the position where to start searching for words 
     int strt = mTxtChangeStart; 

     //Get the editable text 
     Editable txt = getText(); 


     //Back up the starting position to the nearest space 
     try { 
      for(;;) { 
       if(strt <= 0) break; 
       char c = txt.charAt(strt); 

       if(c != ' ' && c != '\t' && c != '\n' && c != '\r') { 
        strt--; 
       } else { 
        break; 
       } 
      } 
     } catch (IndexOutOfBoundsException e) { 
      Log.e("", "Find start position failed: " + e.getMessage()); 
     } 

     //Just seeing how long this part took 
     long findStartPosTime = System.currentTimeMillis(); 
     Log.d("", "Find starting position took " + String.valueOf(System.currentTimeMillis() - findStartPosTime) + " milliseconds"); 

     //the 'end of a word' position 
     int fin = strt; 

     //Get the total length of the search text 
     int totalLength = txt.length(); 

     //Start finding words 
     //This loop is to find the first character of a word 
     //It loops until the current character isnt a space, tab, linebreak etc. 
     while(fin < totalLength && strt < totalLength) { 
      for(;;) { 
       //Not sure why I added these two lines - not needed here 
       //fin++; 
       //if(fin >= totalLength) { break; } //We're at the end of the document 

       //Check if there is a space at the first character. 
       try { 
        for(;;) { //Loop until we find a useable character 
         char c = txt.charAt(strt); 
          if (c == ' ' || c == '\t' || c == '\n' || c == '\r'){ 
          strt++; //Go to the next character if there is a space 
          } else { 
          break; //Found a character (not a space, tab or linebreak) - break the loop 
         } 
        } 
       }catch(IndexOutOfBoundsException e) { 
        Log.e("", e.getMessage()); 
        break; 
       } 

       //Make sure fin isnt less than strt 
       if(strt > fin) { fin = strt; } 

       //Now we search for the end of the word 
       //Loop until we find a space at the end of a word 
       try { 
        for(;;) { 
         char c = txt.charAt(fin); 
         if(c != ' ' && c != '\t' && c != '\n' && c != '\r') { 
          fin++; //Didn't find whitespace here, keep looking 
         } else { 
          break; //Now we found whitespace, end of a word 
         } 
        } 
        break; 
       } catch (IndexOutOfBoundsException e) { 
        //If this happens it should mean it just reached the end of the document. 
        Log.e("", "End of doc? : " + e.getMessage()); 
        break; 
       } 
      } 

      Log.d("", "It took " + String.valueOf(System.currentTimeMillis() - findStartPosTime) + " milliseconds to find a word"); 

      //Make sure fin isnt less that start, again 
      if(strt > fin) { fin = strt; } 

      //Debug time, how long it took to find a word 
      long matchTime = System.currentTimeMillis(); 

      //Found a word, see if it matches a word in our string[] 
      try { 
       for(String mStruct : mStructures) { 
        if(String.valueOf(txt.subSequence(strt, fin)).equals(mStruct)) { 
         //highlight 
         Spannable s = (Spannable) txt; 
         s.setSpan(new ForegroundColorSpan(Color.RED), strt, fin, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
         //Can someone explain why this is still setting the spannable to the main editable??? 
         //It should be set to txt right??? 

         break; 

        } else { 
         /*Spannable s = (Spannable) txt; 
         s.setSpan(new ForegroundColorSpan(Color.BLACK), strt, fin, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
         txt.removeSpan(s);*/ 
        } 
       } 

      }catch (IndexOutOfBoundsException e) { 
       e.printStackTrace(); 
       Log.e("", "word match error: " + e.getMessage()); 
      } 

      //Finally set strt to fin and start again! 
      strt = fin; 
      Log.d("", "match a word time " + String.valueOf(System.currentTimeMillis() - matchTime) + " milliseconds"); 
     }//end main while loop 

     Log.d("", "Syntax Highlight Finished in " + (System.currentTimeMillis() - syntime) + " milliseconds"); 
     mTextChanged = false; 
    } 


} 

"構造" のリソース(php.xml)

<?xml version="1.0" encoding="utf-8"?> 
    <resources> 
     <string-array name="structures"> 
      <item>if</item> 
      <item>else</item> 
      <item>else if</item> 
      <item>while</item> 
      <item>do-while</item> 
      <item>for</item> 
      <item>foreach</item> 
      <item>break</item> 
      <item>continue</item> 
      <item>switch</item> 
      <item>declare</item> 
      <item>return</item> 
      <item>require</item> 
      <item>include</item> 
      <item>require_once</item> 
      <item>include_once</item> 
      <item>goto</item> 
     </string-array> 

</resources> 

誰もがどのように速く、この検索を行うために、任意の提案を持っている:

は、ここに私のEditTextの基本ですか?私はループがたくさんあることは知っていますが、それ以外の方法はわかりません。

ありがとうございます!

+0

字句解析(大きな犬が使っていること)と正規表現(基本的に字句解析があります) – riwalk

+0

この質問はかなりローカライズされており、基本的にcodereview私はそれがcodereview.SEに属するように感じ、それに応じて投票しました。 – vzwick

答えて

1

各文字を見るのではなく、そこにある区切り文字で文字列を分割できますか?それはいくらかスピードアップします。 (String.split())