2015-07-28 9 views
1

Я работаю через приложение для Android, которое я пишу, и пытаюсь привести свой код в соответствие с рекомендациями Linux Studio.getText() из EditText: возможно ли получить «нуль»?

Я следующий код, который выдает предупреждение (некоторый код опущен):

final EditText input = (EditText)view.findViewById(R.id.edit_text); 
Button button  = (Button)view.findViewById(R.id.button); 
button.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     String value = input.getText().toString(); 
     if (value == null || value.length() == 0) { 

Android-студия дает мне предупреждение, что:

'значение == NULL' условие всегда ложь.

Когда я позволяю Android-студия "исправить" эту проблему для меня, она рекомендует:

упрощать 'значение == NULL' к ложному

код становится:

if (value.length() == 0) { 

Я просмотрел исходный код Android (http://www.grepcode.com), и я смущен. В документации для EditText говорится: «EditText - это тонкий шпон поверх TextView, который настраивается для редактирования». Затем метод getText() определяется следующим образом:

@Override 
public Editable getText() { 
    return (Editable) super.getText(); 
} 

Когда я иду в getText() для TextView (в «супер»), я вижу это:

public CharSequence getText() { 
    return mText; 
} 

setText() метод для TextView появляется чтобы запретить значение null, потому что это начало этого метода:

private void setText(CharSequence text, BufferType type, boolean notifyBefore, int oldlen) { 
    if (text == null) { 
     text = ""; 
    } 

Конструктор по умолчанию начинается этот путь, тоже:

public TextView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    mText = ""; 

Таким образом, казалось бы, что не существует никакого способа getText() возвращать значение null, но комментарии на this answer показывают, что это. Ответы на this question также показывают, что это возможно.

Я хотел бы практиковать оборонительное кодирование, поэтому я структурировал мой код так, как я с самого начала, но я не хочу, чтобы делать null чек на то, что не может быть null. Итак, какова наилучшая практика в этом случае?

+0

вы будете проверять как value.equals ("") и ссылается на это также http://stackoverflow.com/a/3321548/4478125 –

+0

Я думаю, что проверка на линт говорит вам кое-что немного иначе, чем то, что вы читаете Это. На самом деле это не имеет значения для if-statement, может ли 'EditText.getText()' возвращать значение null. Потому что, если он возвращает null, то '.toString()' вызовет исключение NullPointerException до того, как будет достигнут оператор if. Поэтому, если if-statement достигнут, значение не может быть null. Поэтому проверка 'value == null' не требуется. – Barend

+0

@Barend Это имеет немного больше смысла. Я понял, что проверка ворса не может быть достаточно умна, чтобы анализировать все слои, которые я сделал. Итак, возникает вопрос, является ли моя строка 'String value = input.getText(). ToString();' уязвима для NPE. – mbm29414

ответ

2

Я думаю, что проверка ворса говорит вам что-то немного по-другому:

String value = input.getText().toString(); 
if (value == null || value.length() == 0) { 

'значение == NULL' всегда ложно.

На самом деле это не имеет значения в этом случае, если EditText.getText() может когда-либо вернуть null. Поскольку, если он возвращает значение null, то .toString() вызовет исключение NullPointerException до того, как будет достигнут оператор if. Поэтому, если if-statement достигнут, значение не может быть нулевым.

Вы можете выкопать весь исходный код Android, и, возможно, вы обнаружите, что для EditText нет возможности вернуть null. Если это так, то вы можете просто проигнорировать предупреждение lint, если знаете, что стандартный редактор EditText находится в вашем приложении.

Однако, в более общем случае, ничто не мешает мне прилипание это в иерархии представлений:

public class EvilEditText extends EditText { 
    // Constructors 

    @Override 
    public Editable getText() { 
     return null; 
    } 
} 

так безопасный вариант должен переписать код, чтобы быть полностью nullsafe:

Editable e = input.getText(); 
String value = (e == null ? null : e.toString()); 
if (TextUtils.isEmpty(value)) { //hat tip to Deepak Goyal's answer. Could also use isEmpty(e) 
+0

Отличный ответ. Благодаря! В чем разница между 'value.isEmpty()' и 'TextUtils.isEmpty (value)'? – mbm29414

+0

Я думаю, что ни «Редактируемый», ни «Строка» не имеет метода 'isEmpty()', поэтому первый не будет компилироваться? – Barend

+0

По словам developer.android.com, это так. Вот описание: «Возвращает true, если длина этой строки равна 0.» Не знаю, как это отличается от «TextUtils». Просто FYI. ;-) – mbm29414

1

Вы можете использовать TextUtils.isEmpty (значение);

final EditText input = (EditText)view.findViewById(R.id.edit_text); 
Button button  = (Button)view.findViewById(R.id.button); 
button.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     String value = input.getText().toString(); 
     if (TextUtils.isEmpty(value)) { 
      // value is empty 
     }else{ 
      // have value 
     } 
+2

Это не отвечает на мой вопрос. Казалось бы, вы не беспокоитесь о NPE с вашим кодом 'input.getText(). ToString', правильно? Таким образом, либо 'getText()' всегда возвращает ненулевое значение, либо 'toString()' может принимать нулевое значение, которое, как я считаю, не верен. Вы видите, что я спрашиваю? – mbm29414

+0

Это все равно NPE, если 'input.getText()' когда-либо возвращает null. – Barend

+0

Нет, он не вернет нулевое значение, он может вернуть вам пустую строку. –

1

Вы, вероятно, получили это предупреждение, потому что ваш value не держит то, что возвращается из EditText#getText() (который возвращает CharSequence), вместо этого он держит отдачу от CharSequence#toString() (который возвращает String).

Для возврата toString() должно быть невозможно вызвать нулевой номер CharSequence, чтобы вернуть null, поэтому lint предупреждает вас, что нулевая проверка не нужна. Вместо этого вы должны сделать нулевую проверку при возврате EditText#getText().

Другими словами, если ваш input.getText() был нулевым, он уже провалился бы без звонка toString(), поэтому ваш нулевой чек никогда не будет достигнут.

0

значение в выражении

String value = input.getText().toString(); 

не будет null. Так как если вход null, он будет генератором NPE для вызова метода input.getText(). и, следовательно, следующий оператор не будет выполняться. Если вы обрабатываете этот NPE Somthing как

  String value = null; 
      if (input!=null) { 
       value = input.getText().toString(); 
      } 
      if (value == null || value.length() == 0){ 

      } 

Тогда вы не получите, что индикацию.

Смежные вопросы