Las ID de recursos de Android de repente no son definitivas, el interruptor () está roto

5 minutos de lectura

Avatar de usuario de Seva Alekseyev
Seva Alekseyev

PREÁMBULO: esta pregunta es bastante obsoleta, se escribió cuando el entorno de desarrollo de Android preferido era Eclipse con el complemento de Android.


Tuve un proyecto Java Android por un tiempo. Hoy actualicé las herramientas de desarrollo de Android a las últimas de Google. Y el proyecto se rompió: recibo un montón de mensajes de error de compilación “las expresiones de caso deben ser expresiones constantes”.

Resulta que el archivo R.java ahora se genera de manera diferente. Anteriormente, tendría un montón de

public static final int MyID=0x12340000;

declaraciones; ahora, se ve (después de una limpieza/reconstrucción) así:

public static int MyID=0x12340000;

final se ha ido. Entonces, todos los interruptores en los ID de recursos que tenía (y tenía algunos) están mal. ¿Qué pasó, por favor? ¿Se trata sólo de mí? ¿Cuál es la razón aquí? ¿Está documentado en algún lugar? Puedo traer final volver de alguna manera?

Esto sucedió ayer, cuando se lanzó el SDK/ADT 14:

A partir de ADT 14, las constantes de recursos en proyectos de biblioteca ya no son definitivas. Esto se explica con mayor detalle en http://tools.android.com/tips/non-constant-fields

Hay una solución rápida disponible de ADT 14: http://tools.android.com/recent/switchstatementconversion

Para citar de la justificación:

Cuando se combinan varios proyectos de biblioteca, los valores reales de los campos (que deben ser únicos) pueden colisionar. Antes de ADT 14, todos los campos eran definitivos, por lo que todas las bibliotecas tenían que volver a compilar todos sus recursos y el código Java asociado junto con el proyecto principal cada vez que se usaban. Esto era malo para el rendimiento, ya que hacía que las compilaciones fueran muy lentas. También impidió la distribución de proyectos de biblioteca que no incluían el código fuente, lo que limitó el alcance de uso de los proyectos de biblioteca.

La razón por la que los campos ya no son definitivos es que significa que los archivos jar de la biblioteca se pueden compilar una vez y reutilizar directamente en otros proyectos. Además de permitir la distribución de la versión binaria de los proyectos de la biblioteca (en r15), esto hace que las compilaciones sean mucho más rápidas.

  • Tiene sentido, en realidad. Veo de dónde vienen. El hecho de que las bibliotecas de Android fueran solo fuentes vinculadas en lugar de bibliotecas compiladas ha sido un problema menor para mí durante algún tiempo. Además, felicitaciones a Google por proporcionar un refactorizador mágico.

    – Seva Alekseyev

    20 de octubre de 2011 a las 19:27

  • Esto es solo una consecuencia de una decisión de diseño idiota por parte del equipo de Android. Cada vez que vea un archivo generado con un montón de constantes de números mágicos, debe mirarlo divertido. Gracias, Google por descifrar un montón de código fuente de sus desarrolladores debido a una completa falta de previsión. Entradas estáticas públicas. ¡¿Mucho mejor?!

    – Nate

    12 de noviembre de 2011 a las 1:15

  • Esta respuesta está marcada como solución, pero no la veo… Muy buenos debates, sugerencias, enlaces de documentación, etc. solamente… ¿Qué es una solución concreta? ¿Qué debo cambiar en mi código para solucionar el problema, por favor, en pocas palabras? O sin solución? – entonces responda en una palabra: “no”. ?

    – Vitaly

    25 de diciembre de 2020 a las 5:56


  • @RussiaDroneFlights ¿Leíste alguno de los enlaces? Dicen que use cláusulas if-else en lugar de declaraciones de cambio si necesita hacer algo condicionalmente con ID de recursos. Las declaraciones de cambio requerirían que las identificaciones sean definitivas, lo que no ha sido desde hace poco más de nueve años.

    – Philipp Reichart

    26 de diciembre de 2020 a las 11:40

Solo agrega paréntesis:

switch (view.getId()) {
    case (R.id.view1):
        break;
    case (R.id.view2):
        break;
}

  • ¿Por qué funciona esto? ¿Y es seguro hacerlo?

    – SM Biggs

    5 de diciembre de 2022 a las 22:49

  • @SMBiggs Creo que lo convierte en una especie de constante, no solo en una referencia. Lo uso algunos meses en modo de producción con muchos clientes y aún no he recibido ningún fallo o queja.

    – M. Marmor

    6 de diciembre de 2022 a las 9:54


Avatar de usuario de AP
punto de acceso

Puede cambiar al uso de declaraciones If/Else y la advertencia desaparecerá.

Muestra:

    @Override
    public void onClick(final View v) {
        //finds which button was pressed
        final int buttonView = v.getId();
        String current = fromEditText.getText().toString();
        if (buttonView == R.id.bA) {
            current += getString(R.string.a);
        } 
  }

  • 😂😭🤣😀❤️ ¡Buena!

    – UNO

    11 de noviembre de 2020 a las 18:12

Google te recomienda usar condiciones si/si no

http://tools.android.com/tips/non-constant-fields

Para cambiarlos automáticamente, puede colocar el signo de intercalación en el switch palabra clave y prensa alternativa + Ingresar en Windows (Opción + Ingresar en Mac) y seleccione Reemplace ‘cambiar’ con ‘si’

Deberías usar ver encuadernación!

android {
    ...
    viewBinding {
        enabled = true
    }
}

  • No funciona con menús. La pregunta original era principalmente sobre ID de menú.

    – Seva Alekseyev

    19 mayo 2021 a las 20:33

  • Agrega muchas clases y tampoco soluciona el problema, solo usa otra forma de identificar y trabajar con vistas.

    – Señor Wabbit

    18 de agosto de 2021 a las 19:24

Simplemente agregue esto recortado en su nivel de módulo build.gradle expediente:

android {
    ...
    lintOptions {
        disable 'NonConstantResourceId'
    }
}

Más:
https://developer.android.com/studio/write/lint#gradle

  • No funciona con menús. La pregunta original era principalmente sobre ID de menú.

    – Seva Alekseyev

    19 mayo 2021 a las 20:33

  • Agrega muchas clases y tampoco soluciona el problema, solo usa otra forma de identificar y trabajar con vistas.

    – Señor Wabbit

    18 de agosto de 2021 a las 19:24

¿Ha sido útil esta solución?