błąd instrukcji case switch: wyrażenia case muszą być wyrażeniami stałymi


131

Moja instrukcja dotycząca przełącznika działa wczoraj doskonale. Ale kiedy uruchomiłem kod wcześniej tego ranka, zaćmienie dało mi błąd podkreślając instrukcje przypadku kolorem czerwonym i mówi: wyrażenia przypadku muszą być stałymi wyrażeniami, są stałe, nie wiem, co się stało. Oto mój kod poniżej:

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;
        }
    }

Wszystkie R.id.int są podkreślone na czerwono.


Czy możesz podać definicję R.id.playbtnitp.? Czy wszystko jest statyczne i ostateczne?
Thomas

2
Prawdopodobnie usunąłeś / zmodyfikowałeś swój układ i te identyfikatory już nie istnieją lub coś w tym rodzaju ...
Vicente Plata

Klasa Rjest zwykle generowana przez narzędzia IDE / dev, więc zwykle jest poprawna dla używanej wersji Androida.
cHao

moje R.id. * są w porządku i istnieją w klasie gen androida ... a także w głównym układzie.
HeartlessArchangel

Odpowiedzi:


277

W zwykłym projekcie systemu Android stałe w klasie R zasobu są deklarowane w następujący sposób:

public static final int main=0x7f030004;

Jednak od ADT 14 w projekcie biblioteki będą deklarowane w następujący sposób:

public static int main=0x7f030004;

Innymi słowy, stałe nie są ostateczne w projekcie biblioteki. Dlatego twój kod nie będzie się już kompilował.

Rozwiązanie tego jest proste: przekonwertuj instrukcję switch na instrukcję 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

Możesz szybko przekonwertować switchinstrukcję na if-elseinstrukcję, korzystając z:

W Eclipse
Przesuń kursor na switchsłowo kluczowe i naciśnij Ctrl+, 1a następnie wybierz

Zamień „przełącznik” na „jeśli-jeszcze”.

W Android Studio
Przesuń kursor na switchsłowo kluczowe i naciśnij Alt+, Entera następnie wybierz

Zamień „przełącznik” na „jeśli”.


zmienić moje oświadczenie switch-case do innego-if .. To po prostu got me zastanawiasz utworzyć nowy android projektu i stosowane oświadczenie switch-case i działać dobrze ..
HeartlessArchangel

1
Może się zdarzyć, że Twój pierwszy projekt korzysta z projektu biblioteki, a nowy nie.
Benito Bertoli

Nie rozumiem, że przykro im naprawdę początkujący tutaj .. można wytłumaczyć
HeartlessArchangel

7
Przynajmniej zaćmienie pozwoli ci automatycznie przekonwertować przełącznik na if / else. kliknij słowo kluczowe switch. następnie naciśnij ctrl-1
Darren Cato

2
Kompilator wymaga, aby wyrażenie było znane w czasie kompilacji. Bez finalsłowa kluczowego zmienną można zmienić w czasie wykonywania.
Benito Bertoli

52

Odznaczenie „Is Library” w projekcie Właściwości zadziałało dla mnie.


2
Kliknij prawym przyciskiem myszy nazwę swojego projektu. Następnie kliknij właściwości -> Android. W prawym dolnym rogu wyskakującego okienka znajduje się sekcja z etykietą „Biblioteka”. Pod nim, jeśli opcja „jest biblioteką” jest zaznaczona, odznacz ją, jeśli nie chcesz, aby Twój projekt był projektem bibliotecznym. Następnie wyczyść i odbuduj. Jeśli chcesz, aby był to projekt biblioteki, musisz zmienić swój przełącznik na warunkowy, jak podano w innym miejscu.
VikingGlen

5
Istnieją powody, dla których projekt biblioteki jest oznaczony jako „Is Library”. To nie jest właściwe rozwiązanie problemu - zepsuje strukturę projektu Androida, powodując, że biblioteki powinny zachowywać się jak zwykłe aplikacje.
ADTC

14

Rozwiązanie można zrobić w ten sposób:

  1. Wystarczy przypisać do wartości do Integer
  2. Zmień zmienną na ostateczną

Przykład:

public static final int cameraRequestCode = 999;

Mam nadzieję, że to ci pomoże.


8

R.id. *, ponieważ ADT 14 nie są bardziej zadeklarowane jako końcowe statyczne int, więc nie można ich używać w konstrukcji przypadku przełącznika. Zamiast tego możesz użyć klauzuli if else.


tak, przeczytałem to na tools.android.com, próbowałem też stworzyć nowy projekt i użyłem powyższego kodu i działa dobrze .. jak to jest?
HeartlessArchangel


6
Dlaczego dokonali tej zmiany, nie ma sensu.
Andrew S

8

Proste rozwiązanie tego problemu to:

Kliknij przełącznik, a następnie naciśnij CTL + 1, zmieni to przełącznik na instrukcję blokującą if-else i rozwiąże problem


7

Co powiesz na to inne rozwiązanie, aby zachować fajny przełącznik zamiast 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);
    }

}

Więc w swoim kodzie możesz to zrobić:

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;
    }
}

Wyliczenia są statyczne, więc będzie to miało bardzo ograniczony wpływ. Jedynym oknem do niepokoju byłoby podwójne wyszukiwanie (najpierw w wewnętrznej tablicy SparseArray, a później w tablicy przełączników)

To powiedziawszy, to wyliczenie można również wykorzystać do płynnego pobierania elementów, w razie potrzeby, zachowując odniesienie do id ... ale to już historia na inny czas.


Wyliczenia są odradzane w systemie Android ze względu na ich nadmiar pamięci; i to jest główny powód, dla którego nigdy nie są używane w AOSP - i powód, dla którego wszędzie widzisz ints.
ADTC


3

Wyrzucał mi ten błąd, gdy używam przełącznika w funkcji ze zmiennymi zadeklarowanymi w mojej klasie:

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;
    }
}

Problem został rozwiązany, gdy zadeklarowałem finalzmiennym na początku zajęć:

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

1
enumjest intw tym przypadku lepszą alternatywą . Obiekt wywołujący metody nie będzie mógł wywołać funkcji o nieprawidłowym typie.
nhahtdh

Mam określone typy int, więc jest ok, jeśli używam ints. Chciałbym jednak poznać przykład z enum: D
aimiliano

i have specific int types so its ok if i use intsTo naprawdę nie ma sensu. Odnośnie przykładu wyliczenia: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

mam na myśli, że przychodzący typ zmiennej int w funkcji zawsze będzie jednym z tych 3 typów, więc nic nie
zepsuje

i mean that the incoming int variable type in the function will always be one of these 3 types so it won't break anythingTo jest twoje założenie. Ktoś inny może wywołać funkcję niepoprawnie z dowolnym numerem. Dzięki enum, nie trzeba zakładać, że jest egzekwowane przez język.
nhahtdh

2

Chciałbym o tym wspomnieć, z taką samą sytuacją spotkałem się, gdy próbowałem dodać bibliotekę do swojego projektu. Nagle wszystkie instrukcje switch zaczęły pokazywać błędy!

Teraz próbowałem usunąć dodaną bibliotekę, nawet wtedy nie działała. jednak „ kiedy wyczyściłem projekt ”, wszystkie błędy po prostu odpadły!


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.