Работа с аннотацией Android @IdRes

Я использовал метод setId класса View. Согласно этому методу

public void setId(@IdRes int id) // This will accept resource id

Когда я попытался использовать этот метод с некоторым жестко закодированным значением int (скажем, 100), тогда этот метод начнет выдавать правильное предупреждение, которое ожидается -

actionButton.setId(100);

Ожидаемый ресурс идентификатора типа.

Но когда я преобразовал это hardcoded значение в метод и никогда не определял, что этот метод вернет @IdRes, Warning будет молчать.

    private int getViewId() {
        return 100;
    }

Вызов метода для установки идентификатора.

 actionButton.setId(getViewId());

Разве оба они одинаковы. Hardcoded int и a int возвращаются из этого метода. Итак, почему в одном случае метод бросает предупреждение, а в другом - молчит.

Ради меня попробовал с StringRes, но я получаю предупреждение в обоих случаях.

 private void setMyString(@StringRes int resourceString) {}

Предупреждение в обоих случаях -

    setMyString(1);
    setMyString(getStringId()); getStringId returns int value

Ответ 1

Это только предупреждение Lint , поскольку метод ожидает, что переменная будет из класса R.id.

Что касается случая значения, возвращаемого методом, Lint не потрудился проверить всю функцию, вернет ли он твердое целое число или фактический идентификатор.

Из документации по @IdRes говорится:

Обозначает, что возвращаемое значение целочисленного параметра, поля или метода как ожидается, будет ссылкой на ресурс идентификатора (например, android.R.id.copy).

Также аннотация просто существует в исходном коде для документации. После компиляции кода аннотация будет удалена.

Ответ 2

В одном случае (@IdRes) вы вызываете метод из API (View.setId()), в то время как в другом вы вызываете метод в своем собственном коде. Кроме того, getViewId() не аннотируется, поэтому из подписи не видно, какой тип int возвращается.

С помощью следующих методов:

private int getUndefinedRes() {
   ...
}

private @IdRes int getIdRes() {
   ...
}

private @StringRes int getStringRes() {
    ...
}

private void setMyString(@StringRes int resourceString) {
}

private void setMyId(@IdRes int resourceId) {
}

Результаты поиска и проверки (как и для Android Studio 2.3.3):

    // API method with definitely wrong value (constant)
    // --> ERROR
    new View(context).setId(100);
    new TextView(context).setText(100);

    // API method with definitely wrong value (from method declaration)
    // --> ERROR
    new View(context).setId(getStringRes());
    new TextView(context).setText(getIdRes());

    // API method with potentially wrong value
    // --> ok
    new View(context).setId(getUndefinedRes());
    new TextView(context).setText(getUndefinedRes());

    // own method with potentially wrong value
    // --> ERROR
    setMyString(getUndefinedRes());
    setMyId(getUndefinedRes());

Кажется, что lint только смотрит на подпись метода.

Это также более мягко, когда вы вызываете метод API: он показывает ошибку, только если очевидно, что вы делаете что-то неправильно. Я думаю, что это, потому что в противном случае заставит всех добавить много аннотаций.

С другой стороны, когда вы добавляете аннотации в свой код, вы выбираете дополнительную серьезность.