我决定必须编写自己的语法荧光笔。到目前为止,它可以正常工作,但是它是实时的(您键入,突出显示),而且速度很慢。

我将尝试解释它是如何工作的。每次用户在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>


任何人有任何建议如何使此搜索更快?我知道我有很多循环,但是我不确定还有其他方法。

非常感谢!

最佳答案

您可以在那里的分隔符上拆分字符串,而不是查看每个字符吗?这样可以加快速度。 (String.split())

关于android - 优化我的语法荧光笔,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7855587/

10-10 05:15