switch case statement error: expressões de caso devem ser expressão constante


128

Minha declaração de caso de mudança funciona perfeitamente bem ontem. Mas quando executo o código esta manhã, o eclipse me deu um erro ao sublinhar as instruções de caso em vermelho e diz: expressões de caso devem ser constantes, é constante, não sei o que aconteceu. Aqui está o meu código abaixo:

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

Todos os R.id.int estão todos sublinhados em vermelho.


Você pode fornecer a definição de R.id.playbtnetc.? Tudo estático e final?
Thomas

2
Provavelmente você excluiu / modificado seu layout e esses ids não existem mais, ou algo assim ...
Vicente Plata

A classe Rgeralmente é gerada pelas ferramentas IDE / dev, por isso geralmente está correta para a versão do Android em uso.
cHao 01/02

meu R.id. * está bem e existe na classe gen do android ... e também no layout principal.
HeartlessArchangel

Respostas:


274

Em um projeto regular do Android, as constantes na classe R do recurso são declaradas assim:

public static final int main=0x7f030004;

No entanto, a partir do ADT 14, em um projeto de biblioteca, eles serão declarados assim:

public static int main=0x7f030004;

Em outras palavras, as constantes não são finais em um projeto de biblioteca. Portanto, seu código não seria mais compilado.

A solução para isso é simples: converta a instrução switch em uma instrução 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

Você pode converter rapidamente uma switchdeclaração em uma if-elsedeclaração usando o seguinte:

No Eclipse
Mova o cursor para a switchpalavra - chave e pressione Ctrl+ 1e selecione

Converta 'switch' para 'if-else'.

No Android Studio
Mova o cursor para a switchpalavra - chave e pressione Alt+ Entere selecione

Substitua 'switch' por 'if'.


i mudar a minha instrução switch-case para else-if .. Ele só me pegou perguntando i criar um novo projeto Android e usou uma instrução switch-case e multa trabalho ..
HeartlessArchangel

1
Pode ser que seu primeiro projeto esteja usando um projeto de biblioteca e seu novo projeto não.
Benito Bertoli

Eu não entendo que im não realmente um novato aqui .. você pode explicar
HeartlessArchangel

7
Pelo menos o eclipse permitirá converter a opção para if / else automaticamente. clique na palavra-chave switch. em seguida, pressione ctrl-1
Darren Cato

1
O compilador precisa que a expressão seja conhecida no momento da compilação. Sem a finalpalavra - chave, uma variável pode ser alterada em tempo de execução.
Benito Bertoli

52

Desmarcar "Is Library" nas propriedades do projeto funcionou para mim.


2
Clique com o botão direito do mouse no nome do seu projeto. Em seguida, clique em Propriedades -> Android. No canto inferior direito do pop-up há uma seção com a tag "Biblioteca". Abaixo dela, se a opção "is Library" estiver marcada, desmarque-a se você não deseja que seu projeto seja um projeto de biblioteca. Em seguida, limpe e reconstrua. Se você quiser que seja um projeto de biblioteca, precisará alterar sua opção para condicional if else, conforme indicado em outro lugar.
VikingGlen

5
Há razões pelas quais um projeto de biblioteca está marcado com "É Biblioteca". Essa não é uma solução adequada para o problema - ela quebrará a estrutura do projeto do Android, fazendo com que o que deveriam ser as bibliotecas se comportem como aplicativos comuns.
ADTC

13

A solução pode ser feita da seguinte maneira:

  1. Apenas atribua o valor a Inteiro
  2. Tornar variável para final

Exemplo:

public static final int cameraRequestCode = 999;

Espero que isso ajude você.


8

R.id. *, uma vez que o ADT 14 não é mais declarado como int estático final, portanto você não pode usá-lo na construção de caso de switch. Você pode usar a cláusula if else.


Sim, eu li isso em tools.android.com, também tentei criar um novo projeto e usei o código acima e funciona muito bem .. como é isso?
HeartlessArchangel

1
tools.android.com/recent/buildchangesinrevision14, consulte a seção " Revisão do projeto da biblioteca"
Blackbelt

6
Por que eles fizeram essa mudança não faz sentido.
Andrew S

8

A solução simples para esse problema é:

Clique no comutador e pressione CTL + 1. Ele mudará o comutador para a declaração de bloco if-else e resolverá o problema.


7

Que tal essa outra solução para manter a boa opção em vez de um 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);
    }

}

Portanto, no seu código, você pode fazer isso:

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

As enums são estáticas, portanto, isso terá um impacto muito limitado. A única janela de preocupação seria a pesquisa dupla envolvida (primeiro no SparseArray interno e depois na tabela de comutadores)

Dito isto, esse enum também pode ser utilizado para buscar os itens de maneira fluente, se necessário, mantendo uma referência ao id ... mas isso é uma história para outra hora.


As enums são desencorajadas no Android devido ao inchaço da memória; e esse é o principal motivo pelo qual eles nunca são usados ​​no AOSP - e o motivo pelo qual você vê ints em todos os lugares.
ADTC


3

Ele estava me lançando esse erro quando utilizava o switch em uma função com variáveis ​​declaradas na minha 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;
    }
}

O problema foi resolvido quando eu declarei finalpara as variáveis ​​no início da classe:

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

1
enumé uma alternativa melhor para intneste caso. O chamador do método não poderá chamar a função com tipo inválido.
N

Eu tenho tipos int específicos, então tudo bem se eu usar ints. No entanto, eu gostaria de saber um exemplo com enum: D
aimiliano

i have specific int types so its ok if i use intsRealmente não faz sentido. Em relação ao exemplo de enum: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

i significa que o tipo de variável int entrada na função será sempre um destes 3 tipos de modo que não irá quebrar nada graças para o exemplo 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 anythingEsta é a sua suposição. Outra pessoa pode chamar a função incorretamente com número arbitrário. Com enum, você não precisa assumir, ele é imposto pelo idioma.
Nhahtdh 12/09/2013

2

Gostaria de mencionar que me deparei com a mesma situação quando tentei adicionar uma biblioteca ao meu projeto. De repente, todas as instruções do switch começaram a mostrar erros!

Agora eu tentei remover a biblioteca que adicionei, mesmo assim não funcionou. como sempre " quando eu limpei o projeto " todos os erros foram disparados!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.