ошибка оператора switch case: выражения case должны быть постоянными выражениями


129

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

public void onClick(View src)
    {
        switch(src.getId()) {
        case R.id.playbtn:
            checkwificonnection();
            break;

        case R.id.stopbtn:
            Log.d(TAG, "onClick: stopping srvice");
            Playbutton.setImageResource(R.drawable.playbtn1);
            Playbutton.setVisibility(0); //visible
            Stopbutton.setVisibility(4); //invisible
            stopService(new Intent(RakistaRadio.this,myservice.class));
            clearstatusbar();
            timer.cancel();
            Title.setText(" ");
            Artist.setText(" ");
            break;

        case R.id.btnmenu:
            openOptionsMenu();
            break;
        }
    }

Все R.id.int подчеркнуты красным.


Можете ли вы дать определение R.id.playbtnи т. Д.? Все ли статично и окончательно?
Томас

2
Вероятно, вы удалили / изменили свой макет, и эти идентификаторы больше не существуют или что-то в этом роде ...
Висенте Плата

Класс Rобычно создается с помощью инструментов IDE / dev, поэтому он обычно подходит для используемой версии Android.
cHao 01

мои R.id. * все в порядке и существуют в классе gen для android .. а также в основном макете.
HeartlessArchangel

Ответы:


274

В обычном Android-проекте константы в классе ресурса R объявляются следующим образом:

public static final int main=0x7f030004;

Однако, начиная с ADT 14, в проекте библиотеки они будут объявлены следующим образом:

public static int main=0x7f030004;

Другими словами, в библиотечном проекте константы не являются окончательными. Поэтому ваш код больше не будет компилироваться.

Решение для этого простое: преобразуйте оператор switch в оператор if-else.

public void onClick(View src)
{
    int id = src.getId();
    if (id == R.id.playbtn){
        checkwificonnection();
    } else if (id == R.id.stopbtn){
        Log.d(TAG, "onClick: stopping srvice");
        Playbutton.setImageResource(R.drawable.playbtn1);
        Playbutton.setVisibility(0); //visible
        Stopbutton.setVisibility(4); //invisible
        stopService(new Intent(RakistaRadio.this,myservice.class));
        clearstatusbar();
        timer.cancel();
        Title.setText(" ");
        Artist.setText(" ");
    } else if (id == R.id.btnmenu){
        openOptionsMenu();
    }
}

http://tools.android.com/tips/non-constant-fields

Вы можете быстро преобразовать switchоператор в if-elseоператор, используя следующее:

В Eclipse
переместите курсор к switchключевому слову и нажмите Ctrl+, 1затем выберите

Преобразуйте switch в if-else.

В Android Studio
переместите курсор к switchключевому слову и нажмите Alt+, Enterзатем выберите

Замените «переключатель» на «если».


Я меняю свой оператор switch-case на оператор else-if .. Это просто заставило меня задуматься, я создаю новый проект для Android, использую оператор switch-case и работаю нормально ..
HeartlessArchangel

1
Возможно, ваш первый проект использует проект библиотеки, а ваш новый - нет.
Бенито Бертоли

я не понимаю, что извините, я действительно новичок здесь .. вы можете объяснить
HeartlessArchangel

7
По крайней мере, eclipse позволит вам автоматически преобразовать переключатель в if / else. щелкните по ключевому слову переключателя. затем нажмите ctrl-1
Даррен Кейто

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

52

У меня сработало снятие флажка «Библиотека» в свойствах проекта.


2
Щелкните правой кнопкой мыши имя вашего проекта. Затем нажмите «Свойства» -> «Android». В правом нижнем углу всплывающего окна находится раздел «Библиотека». Если под ним установлен флажок «Библиотека», снимите его, если вы не хотите, чтобы ваш проект был проектом библиотеки. Затем очистите и восстановите. Если вы хотите, чтобы это был проект библиотеки, вы должны изменить свой переключатель на условное if else, как указано в другом месте.
VikingGlen

5
Есть причины, по которым проект библиотеки помечен как «Библиотека». Это неправильное решение проблемы - это нарушит структуру вашего проекта Android, заставив то, что должно быть библиотеками, вести себя как обычные приложения.
ADTC

13

Решение можно сделать так:

  1. Просто назначить на значение в Integer
  2. Сделать переменную в финале

Пример:

public static final int cameraRequestCode = 999;

Надеюсь, что это поможет вам.


8

R.id. *, поскольку ADT 14 больше не объявляется как final static int, поэтому вы не можете использовать его в конструкции switch case. Вместо этого вы можете использовать предложение if else.


да, я читал это на tools.android.com, я также пытался создать новый проект и использовал приведенный выше код, и он отлично работает .. как это?
HeartlessArchangel


6
Почему они сделали это изменение, не имеет смысла.
Эндрю С.

8

Простое решение этой проблемы:

Щелкните переключатель, а затем нажмите CTL + 1, он изменит ваш переключатель на оператор блока if-else и решит вашу проблему.


7

Как насчет другого решения сохранить красивый переключатель вместо if-else:

private enum LayoutElement {
    NONE(-1),
    PLAY_BUTTON(R.id.playbtn),
    STOP_BUTTON(R.id.stopbtn),
    MENU_BUTTON(R.id.btnmenu);

    private static class _ {
        static SparseArray<LayoutElement> elements = new SparseArray<LayoutElement>();
    }

    LayoutElement(int id) {
        _.elements.put(id, this);
    }

    public static LayoutElement from(View view) {
        return _.elements.get(view.getId(), NONE);
    }

}

Итак, в вашем коде вы можете сделать это:

public void onClick(View src) {
    switch(LayoutElement.from(src)) {
    case PLAY_BUTTTON:
        checkwificonnection();
        break;

    case STOP_BUTTON:
        Log.d(TAG, "onClick: stopping srvice");
        Playbutton.setImageResource(R.drawable.playbtn1);
        Playbutton.setVisibility(0); //visible
        Stopbutton.setVisibility(4); //invisible
        stopService(new Intent(RakistaRadio.this,myservice.class));
        clearstatusbar();
        timer.cancel();
        Title.setText(" ");
        Artist.setText(" ");
        break;

    case MENU_BUTTON:
        openOptionsMenu();
        break;
    }
}

Перечисления статичны, поэтому это будет иметь очень ограниченное влияние. Единственное окно, вызывающее беспокойство, - это задействованный двойной поиск (сначала во внутреннем SparseArray, а затем в таблице переключателей)

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


Перечисления не приветствуются в Android из-за чрезмерного увеличения памяти; и это основная причина, почему они никогда не используются в AOSP, и причина, по которой вы видите целые числа везде.
ADTC


3

Это вызывало у меня эту ошибку, когда я использовал переключатель в функции с переменными, объявленными в моем классе:

private void ShowCalendar(final Activity context, Point p, int type) 
{
    switch (type) {
        case type_cat:
            break;

        case type_region:
            break;

        case type_city:
            break;

        default:
            //sth
            break;
    }
}

Проблема была решена, когда я объявил finalпеременным в начале класса:

final int type_cat=1, type_region=2, type_city=3;

1
enumявляется лучшей альтернативой intв этом случае. Вызывающий метод не сможет вызвать функцию с недопустимым типом.
nhahtdh

У меня есть определенные типы int, поэтому все в порядке, если я использую int. Однако я хотел бы знать пример с enum: D
aimiliano

i have specific int types so its ok if i use intsНа самом деле это не имеет смысла. Что касается примера перечисления: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

Я имею в виду, что тип входящей переменной int в функции всегда будет одним из этих трех типов, поэтому он ничего не сломает, спасибо за пример с перечислением :)
aimiliano

i mean that the incoming int variable type in the function will always be one of these 3 types so it won't break anythingЭто ваше предположение. Кто-то другой может вызвать функцию некорректно с произвольным номером. С enum, вам не нужно предполагать, это обеспечивается языком.
nhahtdh

2

Я хотел бы упомянуть, что я столкнулся с такой же ситуацией, когда пытался добавить библиотеку в свой проект. Внезапно все операторы switch начали показывать ошибки!

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.