erreur d'instruction switch case: les expressions case doivent être une expression constante


128

Ma déclaration switch-case fonctionne parfaitement bien hier. Mais quand j'ai exécuté le code plus tôt ce matin, eclipse m'a donné une erreur soulignant les instructions case en couleur rouge et dit: les expressions case doivent être une expression constante, c'est constant je ne sais pas ce qui s'est passé. Voici mon code ci-dessous:

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

Tous les R.id.int sont tous soulignés en rouge.


Pouvez-vous donner la définition de R.id.playbtnetc.? Tout est-il statique et définitif?
Thomas

2
Vous avez probablement supprimé / modifié votre mise en page et ces identifiants n'existent plus ou quelque chose comme ça ...
Vicente Plata

La classe Rest généralement générée par les outils IDE / dev, elle est donc généralement correcte pour la version d'Android utilisée.
cHao

mes R.id. * sont tous très bien et existent dans la classe gen d'Android .. et c'est aussi dans la mise en page principale.
HeartlessArchangel

Réponses:


274

Dans un projet Android standard, les constantes de la classe de ressource R sont déclarées comme ceci:

public static final int main=0x7f030004;

Cependant, à partir d'ADT 14, dans un projet de bibliothèque, ils seront déclarés comme ceci:

public static int main=0x7f030004;

En d'autres termes, les constantes ne sont pas définitives dans un projet de bibliothèque. Par conséquent, votre code ne se compilerait plus.

La solution pour cela est simple: convertissez l'instruction switch en une instruction 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

Vous pouvez rapidement convertir une switchinstruction en if-elseinstruction en utilisant les éléments suivants:

Dans Eclipse
Déplacez votre curseur sur le switchmot - clé et appuyez sur Ctrl+ 1puis sélectionnez

Convertissez 'switch' en 'if-else'.

Dans Android Studio
Déplacez votre curseur sur le switchmot - clé et appuyez sur Alt+ Enterpuis sélectionnez

Remplacez «switch» par «if».


Je change mon instruction switch-case en instruction else-if .. Cela me fait juste me demander que je crée un nouveau projet Android et utilise une instruction switch-case et fonctionne très bien ..
HeartlessArchangel

1
Il se peut que votre premier projet utilise un projet de bibliothèque et que votre nouveau projet ne le soit pas.
Benito Bertoli

Je ne comprends pas que désolé je suis vraiment un débutant ici .. pouvez-vous expliquer
HeartlessArchangel

7
Au moins eclipse vous permettra de convertir automatiquement le commutateur en if / else. cliquez sur le mot-clé switch. puis appuyez sur ctrl-1
Darren Cato

1
Le compilateur a besoin que l'expression soit connue au moment de la compilation. Sans le finalmot - clé, une variable peut être modifiée lors de l'exécution.
Benito Bertoli

52

Décocher "Est une bibliothèque" dans les propriétés du projet a fonctionné pour moi.


2
Faites un clic droit sur le nom de votre projet. Cliquez ensuite sur propriétés -> Android. En bas à droite de la fenêtre contextuelle se trouve une section intitulée "Bibliothèque". En dessous, si l'option "is Library" est cochée, décochez-la si vous ne voulez pas que votre projet soit un projet de bibliothèque. Ensuite, nettoyez et reconstruisez. Si vous voulez que ce soit un projet de bibliothèque, vous devez changer votre commutateur en conditionnel if else comme indiqué ailleurs.
VikingGlen

5
Il y a des raisons pour lesquelles un projet de bibliothèque est marqué avec "Is Library". Ce n'est pas une solution appropriée au problème - cela brisera la structure de votre projet Android en faisant en sorte que ce qui devrait être des bibliothèques se comporte comme des applications normales.
ADTC

13

La solution peut être faite de cette façon:

  1. Attribuez simplement la valeur à Integer
  2. Faire la variable à finale

Exemple:

public static final int cameraRequestCode = 999;

J'espère que ceci vous aidera.


8

R.id. *, puisque ADT 14 n'est plus déclaré comme int statique final donc vous ne pouvez pas utiliser dans la construction de cas de commutation. Vous pouvez utiliser la clause if else à la place.


oui, j'ai lu cela sur tools.android.com, j'ai également essayé de créer un nouveau projet et utilisé le code ci-dessus et cela fonctionne très bien .. comment est-ce?
HeartlessArchangel

1
tools.android.com/recent/buildchangesinrevision14 voir la section "Library Project Revamp"
Blackbelt

6
Pourquoi ont-ils fait ce changement n'a aucun sens.
Andrew S

8

La solution simple à ce problème est:

Cliquez sur le commutateur , puis appuyez sur CTL + 1, cela changera votre commutateur en instruction de bloc if-else et résoudra votre problème


7

Que diriez-vous de cette autre solution pour garder le commutateur agréable au lieu d'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);
    }

}

Donc, dans votre code, vous pouvez faire ceci:

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

Les énumérations sont statiques donc cela aura un impact très limité. La seule fenêtre de préoccupation serait la double recherche impliquée (d'abord sur le SparseArray interne et plus tard sur la table de commutation)

Cela dit, cette énumération peut également être utilisée pour récupérer les éléments de manière fluide, si nécessaire en gardant une référence à l'id ... mais c'est une histoire pour une autre fois.


Les énumérations sont déconseillées sous Android en raison de leur gonflement de la mémoire; et c'est la raison principale pour laquelle ils ne sont jamais utilisés dans AOSP - et la raison pour laquelle vous voyez des ints partout.
ADTC


3

Cela me lançait cette erreur lorsque j'utilisais switch dans une fonction avec des variables déclarées dans ma 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;
    }
}

Le problème a été résolu lorsque j'ai déclaré finalaux variables au début de la classe:

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

1
enumest une meilleure alternative intdans ce cas. L'appelant de la méthode ne pourra pas appeler la fonction avec un type non valide.
nhahtdh

J'ai des types int spécifiques, donc c'est ok si j'utilise des ints. Cependant, je voudrais connaître un exemple avec enum: D
aimiliano

i have specific int types so its ok if i use intsCela n'a pas vraiment de sens. Concernant l'exemple d'énumération: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

Je veux dire que le type de variable int entrant dans la fonction sera toujours l'un de ces 3 types, donc il ne cassera rien grâce à l'exemple 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 anythingCeci est votre hypothèse. Quelqu'un d'autre peut appeler la fonction de manière incorrecte avec un nombre arbitraire. Avec enum, vous n'avez pas besoin de supposer, il est imposé par la langue.
nhahtdh

2

Je voudrais mentionner que, je suis tombé sur la même situation lorsque j'ai essayé d'ajouter une bibliothèque dans mon projet. Tout d'un coup, toutes les instructions switch ont commencé à afficher des erreurs!

Maintenant, j'ai essayé de supprimer la bibliothèque que j'ai ajoutée, même alors cela ne fonctionnait pas. cependant " quand j'ai nettoyé le projet ", toutes les erreurs se sont produites!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.