androidtextviewspannablestringbuilder

How does TextView's append() method call the replace() method of SpannableStringBuilder


I have this custom SpannableStringBuilder class:

public class ExpressionBuilder extends SpannableStringBuilder{

    public ExpressionBuilder(CharSequence text){
         super(text);
    }

    @Override
    public SpannableStringBuilder replace(int start, int end, CharSequence tb, int tbstart,
                                      int tbend) {
        // do something...
    }

}

And an Editable.Factory needed to converts a TextView into an Editable required by the SpannableStringBuilder:

private final Editable.Factory editableFactory = new Editable.Factory() {
    @Override
    public Editable newEditable(CharSequence source) {
        return new ExpressionBuilder(source);
    }
};

Then attach the TextView to the Editable.Factory:

myTextView.setEditableFactory(editableFactory);

What the above code does basically, is whenever a new string is appended to the TextView, the replace() method is called in the ExpressionBuilder and all its parameters are set. I don't understand how the append() method of the TextView calls the replace() method of the SpannableStringBuilder and how its parameters are set. I searched the documentation but I didn't find any explanation. Any help, please. Thanks.


Solution

  • If you take a look at the Editable Inteface you will see the following:

    /**
     * Convenience for replace(length(), length(), text, 0, text.length())
     * @see #replace(int, int, CharSequence, int, int)
     */
    public Editable append(CharSequence text);
    /**
     * Convenience for replace(length(), length(), text, start, end)
     * @see #replace(int, int, CharSequence, int, int)
     */
    public Editable append(CharSequence text, int start, int end);
    /**
     * Convenience for append(String.valueOf(text)).
     * @see #replace(int, int, CharSequence, int, int)
     */
    public Editable append(char text);
    

    So, it looks like calling append() on a TextView does result in a call to replace() under the hood.

    If we take a closer look by executing the following code in the onCreate() method of an app

    textView.append("123")
    

    we can see that the following chain of calls is made:

    enter image description here

    Line 291 of the SpannableStringBuilder is in the append() method which reads:

    // Documentation from interface
    public SpannableStringBuilder append(CharSequence text, int start, int end) {
        int length = length();
        return replace(length, length, text, start, end);
    }
    

    Here we see that the a call to append() results in a call to replace().