switch errore case statement: le espressioni case devono essere espressione costante


128

La mia dichiarazione sul caso del cambio funziona perfettamente ieri. Ma quando ho eseguito il codice all'inizio di questa mattina eclissi mi ha dato un errore sottolineando le dichiarazioni del caso in rosso e dice: le espressioni del caso devono essere espressione costante, è costante, non so cosa sia successo. Ecco il mio codice qui sotto:

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

Tutti i R.id.int sono tutti sottolineati in rosso.


Potete fornire la definizione di R.id.playbtnecc.? È tutto statico e definitivo?
Thomas,

2
Probabilmente hai cancellato / modificato il layout e quegli ID non esistono più o qualcosa del genere ...
Vicente Plata,

La classe Rè generalmente generata dagli strumenti IDE / dev, quindi di solito è corretta per la versione di Android in uso.
cHao,

i miei R.id. * stanno tutti bene ed esistono nella classe gen di android .. ed è anche nel layout principale.
HeartlessArchangel,

Risposte:


274

In un normale progetto Android, le costanti nella classe R della risorsa sono dichiarate in questo modo:

public static final int main=0x7f030004;

Tuttavia, a partire da ADT 14, in un progetto di biblioteca, saranno dichiarati così:

public static int main=0x7f030004;

In altre parole, le costanti non sono definitive in un progetto di biblioteca. Pertanto il codice non verrà più compilato.

La soluzione è semplice: converti l'istruzione switch in un'istruzione 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

È possibile convertire rapidamente switchun'istruzione in if-elseun'istruzione utilizzando quanto segue:

In Eclipse
Spostare il cursore sulla switchparola chiave e premere Ctrl+, 1quindi selezionare

Converti "switch" in "if-else".

In Android Studio
Spostare il cursore sulla switchparola chiave e premere Alt+, Enterquindi selezionare

Sostituisci "switch" con "if".


cambio la mia istruzione switch-case in un'istruzione else-if .. Mi ha fatto solo pensare di creare un nuovo progetto Android e ho usato un'istruzione switch-case e lavorare bene ..
HeartlessArchangel

1
È possibile che il tuo primo progetto stia utilizzando un progetto di libreria e il tuo nuovo progetto no.
Benito Bertoli,

non capisco che scusa sono davvero un principiante qui .. puoi spiegare
HeartlessArchangel

7
Almeno eclipse ti permetterà di convertire automaticamente in if / else. fai clic sulla parola chiave switch. quindi premi ctrl-1
Darren Cato il

1
Il compilatore richiede che l'espressione sia nota al momento della compilazione. Senza la finalparola chiave, una variabile può essere modificata in fase di esecuzione.
Benito Bertoli,

52

Deselezionando "Is Library" nel progetto Properties ha funzionato per me.


2
Fare clic con il tasto destro sul nome del progetto. Quindi fare clic su Proprietà -> Android. Nella parte inferiore destra del popup è presente una sezione "Libreria". Sotto di essa, se l'opzione "is Library" è selezionata, deselezionala se non vuoi che il tuo progetto sia un progetto di libreria. Quindi pulire e ricostruire. Se vuoi che sia un progetto di libreria, devi cambiare il tuo passaggio in un if if condizionale come indicato altrove.
VikingGlen,

5
Ci sono ragioni per cui un progetto di biblioteca è contrassegnato con "Is Library". Questa non è una soluzione adeguata al problema: romperà la struttura del progetto Android creando quelle che dovrebbero essere le librerie per comportarsi come normali app.
ADTC

13

La soluzione può essere fatta in questo modo:

  1. Basta assegnare il valore a Integer
  2. Rendi variabile a finale

Esempio:

public static final int cameraRequestCode = 999;

Spero che questo ti possa aiutare.


8

R.id. *, poiché ADT 14 non viene più dichiarato come int statico finale, quindi non è possibile utilizzarlo nel costrutto switch case. È possibile utilizzare invece la clausola if else.


sì, l'ho letto su tools.android.com, ho anche provato a creare un nuovo progetto e ho usato il codice sopra e funziona benissimo .. come va?
HeartlessArchangel,

1
tools.android.com/recent/buildchangesinrevision14 vedi la sezione "Revamp del progetto della biblioteca"
Blackbelt

6
Perché hanno apportato questo cambiamento non ha senso.
Andrew S,

8

La soluzione semplice per questo problema è:

Fare clic sull'interruttore e quindi premere CTL + 1, cambierà il passaggio all'istruzione di blocco if-else e risolverà il problema


7

Che ne dici di questa altra soluzione per mantenere il bel passaggio invece di un 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);
    }

}

Quindi nel tuo codice puoi farlo:

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

Gli enum sono statici, quindi questo avrà un impatto molto limitato. L'unica finestra di preoccupazione sarebbe la doppia ricerca coinvolta (prima su SparseArray interno e successivamente sulla tabella switch)

Detto questo, questo enum può anche essere utilizzato per recuperare gli oggetti in modo fluente, se necessario mantenendo un riferimento all'ID ... ma questa è una storia per un'altra volta.


Gli enumeratori sono scoraggiati in Android a causa della loro memoria gonfia; e questo è il motivo principale per cui non sono mai stati utilizzati in AOSP - e il motivo per cui vedete ints ovunque.
ADTC


3

Mi stava lanciando questo errore quando usavo switch in una funzione con variabili dichiarate nella mia classe:

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

Il problema è stato risolto quando ho dichiarato finalalle variabili all'inizio della classe:

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

1
enumè un'alternativa migliore a intin questo caso. Il chiamante del metodo non sarà in grado di chiamare la funzione con un tipo non valido.
nhahtdh,

ho tipi int specifici, quindi va bene se uso ints. Tuttavia vorrei un esempio con enum: D
aimiliano,

i have specific int types so its ok if i use intsNon ha davvero senso. Per quanto riguarda l'esempio enum: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh,

intendo che il tipo di variabile int in arrivo nella funzione sarà sempre uno di questi 3 tipi, quindi non romperà nulla grazie all'esempio 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 anythingQuesto è il tuo presupposto. Qualcun altro può chiamare la funzione in modo errato con un numero arbitrario. Con enum, non è necessario assumere, è imposto dalla lingua.
nhahtdh,

2

Vorrei menzionarlo, mi sono imbattuto nella stessa situazione quando ho provato ad aggiungere una biblioteca al mio progetto. All'improvviso tutte le istruzioni switch hanno iniziato a mostrare errori!

Ora ho provato a rimuovere la libreria che ho aggiunto, anche se non ha funzionato. quanto mai " quando ho pulito il progetto " tutti gli errori sono appena scomparsi!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.