помилка оператора оператора switch: вирази регістру повинні бути постійними виразами


128

Моя заява про вимикач працює вчора відмінно. Але коли я запустив код раніше цього ранку, затемнення зачинило мені помилку, підкреслюючи виписки справи червоним кольором, і говорить: виразки регістру повинні бути постійними виразами, це постійно, я не знаю, що сталося. Ось мій код нижче:

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
Можливо, ви видалили / змінили ваш макет, і ці ідентифікатори вже не існують чи щось подібне ...
Vicente Plata

Клас Rзазвичай генерується інструментами IDE / dev, тому зазвичай він правильний для версії Android, що використовується.
cHao

мій R.id. * все добре і існує в ген-класі андроїда .. і його також в основній версії.
Безсердечний Архангел

Відповіді:


274

У звичайному проекті Android константи в ресурсному класі R оголошуються так:

public static final int main=0x7f030004;

Однак станом на ADT 14 у бібліотечному проекті вони будуть оголошені так:

public static int main=0x7f030004;

Іншими словами, константи не є остаточними в бібліотечному проекті. Тому ваш код більше не буде компілюватися.

Рішення для цього просте: Перетворіть оператор переключення в оператор 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оператор, використовуючи наступне:

У затемненні
Перемістіть курсор на switchключове слово та натисніть Ctrl+, 1а потім виберіть

Перетворіть "перемикач" на "якщо ні".

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

Замініть "перемикач" на "якщо".


я змінив свою заяву випадку переключення на інше - якщо заява .. Мені просто стало цікаво, що я створив новий проект для Android і використав заяву про вимикач і добре працюю ..
HeartlessArchangel

1
Можливо, ваш перший проект використовує бібліотечний проект, а ваш новий проект - не так.
Беніто Бертолі

я не розумію, що шкода їм насправді для початківців тут .. чи можете ви пояснити
HeartlessArchangel

7
Принаймні затемнення дозволить вам перетворити перемикач на функцію if / else автоматично. натисніть на ключове слово. потім вдарив ctrl-1
Даррен Катон

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

52

Знявши прапорець "Є бібліотека" у проекті Властивості, працював на мене.


2
Клацніть правою кнопкою миші на назві проекту. Потім натисніть на властивості -> Android. У нижній правій частині спливаючого вікна розташований розділ з написом "Бібліотека". Під ним, якщо встановлено прапорець "є бібліотека", зніміть його, якщо ви не хочете, щоб ваш проект був бібліотечним проектом. Потім очистіть і відновіть. Якщо ви хочете, щоб це був бібліотечний проект, вам доведеться змінити свій перемикач на if if умовно, як зазначено в іншому місці.
VikingGlen

5
Є причини, чому проект бібліотеки позначається символом "Є бібліотека". Це не належне рішення проблеми - воно порушить вашу структуру проекту Android, створивши те, що бібліотеки повинні вести себе як звичайні програми.
ADTC

13

Рішення можна зробити таким чином:

  1. Просто призначити на значення в Integer
  2. Зробити змінною до фінальної

Приклад:

public static final int cameraRequestCode = 999;

Сподіваюся, що це вам допоможе.


8

R.id. *, оскільки ADT 14 більше не оголошується як кінцевий статичний int, тому ви не можете використовувати в конструкції корпусу комутатора. Ви можете замість цього використати пункт if else.


так, я прочитав це на tools.android.com, я також спробував створити новий проект і використав код вище, і він працює чудово .. як це?
Безсердечний Архангел

1
tools.android.com/recent/buildchangesinrevision14 див. розділ « Перепрограмування бібліотечних проектів»
Blackbelt

6
Чому вони внесли цю зміну, немає сенсу.
Andrew S

8

Просте рішення цієї проблеми:

Натисніть на перемикач, а потім натисніть CTL + 1, це змінить ваш перемикач на оператор блоку if-else і вирішить вашу проблему


7

Як щодо цього іншого рішення, щоб зберегти приємний перемикач замість того, якщо не потрібно:

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, так що добре, якщо я використовую ints. Однак я хотів би знати приклад із перерахунком: D
aimiliano

i have specific int types so its ok if i use intsЦе насправді не має сенсу. Щодо прикладу enum: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

я маю на увазі, що тип вхідної змінної типу int завжди буде одним з цих 3 типів, тому він нічого не порушить завдяки прикладу enum :)
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

Хотілося б зазначити, що я зіткнувся з тією ж ситуацією, коли спробував додати бібліотеку до свого проекту. Раптом усі заяви переключення почали показувати помилки!

Тепер я спробував видалити бібліотеку, яку я додав, навіть тоді це не вийшло. як коли-небудь " коли я прибирав проект ", всі помилки просто пішли!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.