我決定我必須寫我自己的語法熒光筆。到目前爲止它正在工作,但它是實時的(你鍵入,它突出顯示)並且很慢。優化我的語法熒光筆
我會試着解釋它是如何工作的。每次用戶在EditText中鍵入內容時,它都會運行突出顯示器(通過TextWatcher)。熒光筆搜索文本直到找到單詞的開頭,然後搜索,直到找到同一單詞的結尾。一旦它找到一個單詞,它將通過一組關鍵字進行搜索,如果它找到了一個匹配項,它會在該位置設置一個可跨越的字符串。它保持循環直到到達文檔的末尾。
同樣,它的工作到目前爲止(只是在繼續使用這種方法之前嘗試這個想法),但它太慢了。有些時候,只需要經過幾行就可以花費一秒多的時間。它減慢了文本在EditText中出現的速度。 - 在用戶輸入的最後一個位置輸入文本後,我還設置了突出顯示器的起始位置,因此每次都不需要瀏覽整個文檔,它有一點幫助,但不是很大。
這裏是我的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>
任何人有任何建議,如何使搜索更快?我知道我有很多循環,但我不知道如何去做。
非常感謝!
兩個提示讓你去:詞法分析(大狗使用什麼)和正則表達式(基本上是什麼詞法分析) – riwalk
由於這個問題是相當本地化的,基本上是一個codereview ,我覺得它屬於codereview.SE並相應投票。 – vzwick