TargetApi не учитывается

В одном из наших методов мы используем smoothScrolling в виде списка. Поскольку этот метод недоступен до уровня API 8 (FROYO), мы использовали аннотацию TargetApi, чтобы предотвратить вызов метода в предыдущих версиях SDK.

Как вы можете видеть, мы используем аннотацию TargetApi как в определении класса, так и в операторах, которые используют объекты класса. Это больше, чем нужно.

Наша проблема заключается в том, что аннотация TargetApi не учитывается и делает наш эмулятор крахом в версии ECLAIR (SDK 7). Прослеживая, мы просто понимаем, что код, который должен выполняться только в версиях 8+, также выполняется в версии 7.

Мы что-то упускаем?

Этот код находится в слушателе:

@TargetApi(8) private final class MyOnMenuExpandListener implements OnMenuExpandListener { @Override public void onMenuExpanded( int position ) { doScrollIfNeeded( position ); } @Override public void onMenuCollapsed( int position ) { doScrollIfNeeded( position ); } protected void doScrollIfNeeded( int position ) { if ( mListViewDocuments.getLastVisiblePosition() - 2 < position ) { mListViewDocuments.smoothScrollToPosition( position + 1 ); } } } 

И слушатель зарегистрирован таким образом:

 @TargetApi(8) private void allowSmothScrollIfSupported() { if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ) { //This if should not be necessary with annotation but it is not taken into account by emulator Log.d( LOG_TAG, "Smooth scroll support installed." ); folderContentAdapter.setOnMenuExpandListener( new MyOnMenuExpandListener() ); } } 

BTW, мы запускаем код в режиме отладки, поэтому проблема не связана с аннулированием обфускации.

Thx заранее!

Solutions Collecting From Web of "TargetApi не учитывается"

@TargetApi не предотвращает запуск какого-либо кода, это просто для аннотирования кода и предотвращения ошибок компилятора для новых API, как только вы знаете, что вы вызываете их только условно.

Вам все равно нужно добавить что-то по строкам

 if (Build.VERSION.SDK_INT > 7){ //... } 

Почти год назад мы больше думали об этом, я хотел бы добавить крошечное дополнение к ответу @Guykun:

@TargetApi будет использоваться только инструментами для разработчиков: «Эй, не используйте этот метод ниже XXX android SDK». Обычно ворсистый.

Итак, если вы создаете такой метод, как:

 if (Build.VERSION.SDK_INT > 7){ //... } 

То вы должны добавить @TargetApi (7) в подпись вашего метода.

НО , если вы добавляете инструкцию else и предоставляете альтернативу, которая заставляет ее работать для всех версий Android, например:

 if (Build.VERSION.SDK_INT > 7){ //... } else { //... } 

То вам не следует добавлять @TargetApi (7) в подпись вашего метода. В противном случае другие разработчики подумают, что они не могут использовать ваш метод belw api level 7, но, действительно, это сработает и для них.

Поэтому эту аннотацию необходимо использовать для статического анализа для указания минимального уровня api, поддерживаемого этим методом. Как в :

 @TargetApi( 7 ) public void foo() { if (Build.VERSION.SDK_INT > 7){ //... else if (Build.VERSION.SDK_INT > 10){ //... } } 

И даже лучше, используйте константы, определенные в android.Build.VERSION_CODES.* .

Кстати, вы бы заметили, что это действительно бесполезно для частных методов, за исключением получения более чистого кода и содействия продвижению этого метода в будущем.

Чтобы принудительно использовать ошибку lint при использовании метода, направленного на более высокий уровень Api, вы можете использовать TargetApi вместо TargetApi и всякий раз, когда вы попытаетесь использовать этот метод без проверки кода версии, вы получите ошибку компиляции.

Это то, что в документации говорится о RequiresApi

Это похоже на старую аннотацию @TargetApi, но более четко выражает, что это требование для вызывающего, а не используется для «подавления» предупреждений в методе, превышающем minSdkVersion.