error de declaración de cambio de caso: las expresiones de caso deben ser expresiones constantes


128

Mi declaración de cambio de caso funciona perfectamente bien ayer. Pero cuando ejecuté el código más temprano esta mañana, eclipse me dio un error subrayando las declaraciones de casos en color rojo y dice: las expresiones de casos deben ser expresiones constantes, es constante, no sé lo que sucedió. Aquí está mi código a continuación:

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 los R.id.int están subrayados en rojo.


¿Puedes proporcionar la definición de R.id.playbtnetc.? ¿Es todo estático y final?
Thomas

2
Probablemente eliminó / modificó su diseño y esos identificadores ya no existen o algo así ...
Vicente Plata

La clase Rgeneralmente es generada por las herramientas IDE / dev, por lo que generalmente es correcta para la versión de Android en uso.
cHao

my R.id. * están bien y existen en la clase gen de android ... y también en el diseño principal.
HeartlessArchangel

Respuestas:


274

En un proyecto normal de Android, las constantes en la clase de recursos R se declaran así:

public static final int main=0x7f030004;

Sin embargo, a partir de ADT 14, en un proyecto de biblioteca, se declararán así:

public static int main=0x7f030004;

En otras palabras, las constantes no son finales en un proyecto de biblioteca. Por lo tanto, su código ya no se compilará.

La solución para esto es simple: convertir la instrucción switch en una instrucción 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

Puede convertir rápidamente una switchdeclaración en una if-elsedeclaración utilizando lo siguiente:

En Eclipse
Mueva su cursor a la switchpalabra clave y presione Ctrl+ 1luego seleccione

Convierta 'switch' a 'if-else'.

En Android Studio,
mueva el cursor a la switchpalabra clave y presione Alt+ y Enterluego seleccione

Reemplace 'interruptor' con 'si'.


Puedo cambiar mi declaración switch de los casos a los demás-if .. Simplemente me consiguió preguntándose i crear un nuevo proyecto androide y utiliza una sentencia switch de los casos y funcionan bien ..
HeartlessArchangel

1
Puede ser que su primer proyecto esté usando un proyecto de biblioteca y su nuevo proyecto no.
Benito Bertoli

no entiendo que lo siento, soy realmente un principiante aquí ... ¿puedes explicar
HeartlessArchangel

77
Al menos eclipse le permitirá convertir el interruptor a if / else automáticamente. haga clic en la palabra clave del interruptor. luego presione ctrl-1
Darren Cato

1
El compilador necesita que la expresión se conozca en el momento de la compilación. Sin la finalpalabra clave, una variable se puede cambiar en tiempo de ejecución.
Benito Bertoli

52

Desmarcar "Es la biblioteca" en el proyecto Propiedades funcionó para mí.


2
Haga clic derecho en el nombre de su proyecto. Luego haga clic en propiedades -> Android. En la esquina inferior derecha de la ventana emergente hay una sección etiquetada como "Biblioteca". Debajo, si la opción "es Biblioteca" está marcada, desactívela si no desea que su proyecto sea una biblioteca. Luego limpiar y reconstruir. Si desea que sea un proyecto de biblioteca, debe cambiar su cambio a un condicional, si no, como se indica en otro lugar.
VikingGlen

55
Hay razones por las que un proyecto de biblioteca está marcado con "Es biblioteca". Esta no es una solución adecuada al problema: romperá la estructura de su proyecto de Android al hacer que las bibliotecas se comporten como aplicaciones normales.
ADTC

13

La solución se puede hacer de esta manera:

  1. Simplemente asigne el valor a Integer
  2. Hacer variable a final

Ejemplo:

public static final int cameraRequestCode = 999;

Espero que esto te ayudará.


8

R.id. *, ya que ADT 14 ya no se declara como int estático final, por lo que no puede usarlo en la construcción de mayúsculas y minúsculas. Puede usar la cláusula if else en su lugar.


Sí, lo he leído en tools.android.com, también intenté crear un nuevo proyecto y usé el código anterior y funciona bien ... ¿cómo es eso?
HeartlessArchangel

1
tools.android.com/recent/buildchangesinrevision14 vea la sección " Renovación del proyecto de biblioteca"
Blackbelt

66
Por qué hicieron este cambio no tiene sentido.
Andrew S

8

La solución simple para este problema es:

Haga clic en el interruptor y luego presione CTL + 1, cambiará su cambio a la instrucción de bloqueo if-else, y resolverá su problema


7

¿Qué tal esta otra solución para mantener el buen interruptor en lugar de 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);
    }

}

Entonces, en su código, puede hacer esto:

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

Las enumeraciones son estáticas, por lo que esto tendrá un impacto muy limitado. La única ventana de preocupación sería la doble búsqueda involucrada (primero en el SparseArray interno y luego en la tabla de interruptores)

Dicho esto, esta enumeración también se puede utilizar para buscar los elementos de manera fluida, si es necesario manteniendo una referencia a la identificación ... pero esa es una historia para otro momento.


Enums no se recomienda en Android debido a su memoria hinchada; y esa es la razón principal por la que nunca se usan en AOSP, y la razón por la que se ven entradas en todas partes.
ADTC


3

Me estaba arrojando este error cuando uso switch en una función con variables declaradas en mi clase:

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

El problema se resolvió cuando declaró finala las variables al comienzo de la clase:

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

1
enumEs una alternativa mejor a inten este caso. La persona que llama del método no podrá llamar a la función con un tipo no válido.
nhahtdh

Tengo tipos int específicos, así que está bien si uso ints. Sin embargo, me gustaría saber un ejemplo con enum: D
aimiliano

i have specific int types so its ok if i use intsRealmente no tiene sentido. Con respecto al ejemplo de enum: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

Quiero decir que el tipo de variable int entrante en la función siempre será uno de estos 3 tipos, por lo que no se romperá nada, gracias por el ejemplo 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 es tu suposición. Alguien más puede llamar a la función incorrectamente con un número arbitrario. Con enum, no es necesario suponer, se aplica por el idioma.
nhahtdh

2

Me gustaría mencionar que me encontré con la misma situación cuando intenté agregar una biblioteca a mi proyecto. ¡De repente, todas las declaraciones de cambio comenzaron a mostrar errores!

Ahora intenté eliminar la biblioteca que agregué, incluso entonces no funcionó. sin embargo, " cuando limpié el proyecto ", ¡todos los errores se salieron!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.