Что означает этот комментарий в коде EditText.java? - PullRequest
0 голосов
/ 14 ноября 2018

Я просмотрел EditText.java , в строке 109 приведенный ниже комментарий можно увидеть в методе getText():

// This can only happen during construction.

Какова его цель?

Спасибо

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Я более подробно остановлюсь на ответе Андреаса, предназначенном для этого конкретного набора классов.

EditText - это подкласс TextView.Вот почему он объявлен как:

class EditText extends TextView (Упрощенный ...)

Конструкторы EditText выглядят так:

public EditText(Context context) {
    this(context, null);
}
public EditText(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.editTextStyle);
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr) {
    this(context, attrs, defStyleAttr, 0);
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

Обратите внимание, как каждый конструктор вызывает другой допоследний (длинный).Это сложно, потому что он вызывает super(…), то есть теперь он вызывает конструктор суперкласса (TextView).

EditText - это просто специализированный TextView, как мы можем из этого сделать вывод;TextView также объявляет переменную с именем text, которую, конечно, также использует EditText.Когда вы запрашиваете EditText для text, он просто использует код, который уже есть у TextView и который вы обнаружили:

@Override
public Editable getText() {
    CharSequence text = super.getText();
    // This can only happen during construction.
    if (text == null) {
        return null;
    }

    [rest of code removed for clarity]
}

Поэтому он запрашивает у super (TextView) text;почему этот текст может быть нулевым?Чтобы ответить на этот вопрос, вам нужно взглянуть на саму TextView (https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/TextView.java).

около 1000 строк кода позже ... TextView объявляет свои конструкторы; я вставлю один для простоты, но они очень просты:

public TextView(Context context) {
     this(context, null);
}

Обратите внимание, что они снова вызывают this(…) и цепочку конструкцию ... один конструктор вызывает другой и так далее ... до последнего большого для TextViewдостигается ...

@SuppressWarnings("deprecation")
public TextView(
        Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    // TextView is important by default, unless app developer overrode attribute.
    if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
        setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
    }
    setTextInternal("");
    [rest of code removed for clarity]

Обратите внимание, что этот конструктор вызывает setTextInternal(""), что выглядит подозрительно! Он устанавливает текст как пустую строку при построении, так что это будет невозможно для TextView иметь нулевой текст после завершения работы этого конструктора ( вы можете использовать отражение ... но давайте не будем идти туда ), поскольку конструкторы EditText объединены в цепочку и заканчиваются всегда вызывая конструкторы TextView, этот метод setTextInternal("") является гарантированно вызываемым в какой-то момент во время конструирования объекта в Java (вот что такое Конструкторы и это Javaконтракт, который разрушил бы половину мира, если бы он был ненадежным!).

Что делает этот метод?

Очевидно, куча внутренних вещей, среди прочего ...

// Update mText and mPrecomputed
private void setTextInternal(@Nullable CharSequence text) {
    mText = text; // #### THIS IS WHERE IT SETS THE TEXT TO NON NULL ("").
    mSpannable = (text instanceof Spannable) ? (Spannable) text : null;
    mPrecomputed = (text instanceof PrecomputedText) ? (PrecomputedText) text : null;
}

Если вы помните, что EditText#getText() называется super.getText() Угадайте, как это выглядит в супер?(TextView):

public CharSequence getText() {
    return mText;
}

Правильно, та же самая ссылка / экземпляр mText, которую setTextInternal() изменили во время конструирования TextView.

Вот почему во время построения (и до вызова setTextInternal(""), поле mText (доступ к которому осуществляется через getText()) может быть нулевым, но не после.

¯\_(ツ)_/¯

Честно говоря, я даже не знаю, почему они это делают, и комментарий кажется довольно глупым, но, как вы, наверное, уже догадались, эти классы представляют собой тысячи строккод, и каждый склонен полагать, что должна существовать причина для его существования; лучшее, что вы можете сделать, это начать анализировать весь класс TextView. Удачи с этим.:)

0 голосов
/ 14 ноября 2018

Цель комментария состоит в том, чтобы сообщить любому программисту, который думает, что следующее утверждение является избыточным, то есть, что text никогда не может быть null, что они ошибочны, потому что может произойти во время построенияобъекта EditText, поэтому не удаляйте оператор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...