Что лучше: @SuppressLint или @TargetApi?

100

В моем приложении есть проблемы с StrictModeдобавлением фрагмента кода, который в основном отключает расширение StrictModeHelper. Однако Линт жалуется setThreadPolicy()сейчас и предлагает либо добавить

@SuppressLint 'NewApi'

или

@TargetApi(Build.VERSION_CODES.GINGERBREAD)

к onCreate()событию представления.

Какой метод предпочтительнее .. или они в основном делают то же самое?

Ричи
источник

Ответы:

176

В моем приложении есть проблемы с StrictMode, и я добавил фрагмент кода, который в основном отключает StrictModeHelper.

Пожалуйста, исправьте сетевую ошибку.

Какой метод предпочтительнее .. или они в основном делают то же самое?

@TargetApiи @SuppressLintимеют тот же основной эффект: они подавляют ошибку Lint.

Разница в том, что с @TargetApiпомощью параметра вы объявляете, к какому уровню API вы обратились в своем коде, чтобы ошибка могла появиться снова, если вы позже измените метод, чтобы попытаться сослаться на что-то более новое, чем уровень API, указанный в @TargetApi.

Например, предположим, что вместо того, чтобы блокировать StrictModeжалобы на вашу сетевую ошибку, вы пытаетесь обойти проблему AsyncTaskсериализации в более новых версиях Android. У вас есть такой метод в вашем коде, чтобы выбрать пул потоков на новых устройствах и использовать многопоточное поведение по умолчанию на старых устройствах:

  @TargetApi(11)
  static public <T> void executeAsyncTask(AsyncTask<T, ?, ?> task,
                                          T... params) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
      task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    }
    else {
      task.execute(params);
    }
  }

Наличие @TargetApi(11)означает, что если Lint обнаружит, что я использую что-то новее моего android:minSdkVersion, но до уровня API 11, Lint не будет жаловаться. В данном случае это работает. Если, однако, я изменил этот метод для ссылки на что-то, что не было добавлено до уровня API 14, тогда снова появится ошибка Lint, потому что моя @TargetApi(11)аннотация говорит, что я исправил код для работы только на уровне API 11 и ниже , а не API уровня 14 и ниже и выше.

Используя @SuppressLint('NewApi'), я потеряю ошибку Lint для любого уровня API, независимо от того, на что ссылается мой код и что мой код настроен для обработки.

Следовательно, @TargetApiэто предпочтительная аннотация, поскольку она позволяет вам более детально сказать инструментам сборки: «Хорошо, я исправил эту категорию проблем».

CommonsWare
источник
Я знаю, что использование асинхронного подхода было бы предпочтительнее, просто в моем конкретном случае я буду придерживаться обходного пути. Спасибо за это подробное и очень понятное объяснение - и, если возможно, спасибо также за ваши очень полезные веб-страницы, которые очень помогли мне понять некоторые концепции программирования Android! R.
Richey
9
@richey: «в моем конкретном случае я буду придерживаться обходного пути» - это не очень хорошая идея. Мобильные устройства мобильны. Сетевые соединения довольно нестабильны и могут занять значительно больше времени в различных обстоятельствах (например, при слабом сигнале). Выполнение сетевого ввода-вывода в основном потоке приложения означает, что ваше приложение случайно выйдет из строя с ошибкой ANR в поле.
CommonsWare
2
Вау, ваш пример кода - это ТОЧНЫЙ код, который я пытаюсь написать! Какое совпадение :)
Илья Коган
4
Разве не было бы более аккуратным / последовательным использование @TargetApi (Build.VERSION_CODES.HONEYCOMB), если вы используете Build.VERSION_CODES.HONEYCOMB в операторе if?
Оливер Пирмейн,
1
«что я исправил код для работы только на уровне API 11 и ниже, а не на уровне API 14 и ниже». - разве вы не имеете в виду "и выше"?
arekolek 03