2012-03-18 17 views
13

Estoy creando un proyecto de biblioteca para varias aplicaciones de Android. Todas las aplicaciones tienen alguna funcionalidad común que deseo incluir en el proyecto de biblioteca, pero las funciones del proyecto de biblioteca requieren el uso de constantes específicas de la aplicaciónAndroid, ¿la mejor manera de proporcionar constantes específicas de aplicaciones en un proyecto de biblioteca?

Estoy buscando una forma de proporcionar a las funciones de la biblioteca los nombres de las constantes y permitir que cada aplicación para definir ellos

un ejemplo de una constante aplicación específica y cómo se utiliza en el proyecto de biblioteca

public class AppConstants { 
    public static final long APP_ID = 6;//Needs to be set for each app 
} 

public static long getCurrentAppId(Context context) { 
    return getLongPreference(context, CURRENT_APP_ID_KEY, AppConstants.APP_ID); 
} 

Esto es sólo un ejemplo de aproximadamente 60 constantes que necesitan ser definida para cada aplicación para un gran número de funciones de la biblioteca

Obviamente, yo podría tan sólo importar/incluir el archivo app_constants.java específica del proyecto, pero esto no es posible en los archivos de proyecto de la biblioteca, ya que no tiene ni idea acerca de las aplicaciones específicas (con razón)

Así ¿Cuál es la mejor manera de que cada aplicación específica anule las constantes?

actualización me llevó mucho tiempo decidir cuál de las excelentes respuestas se me ha proporcionado con el mejor satisfizo mis necesidades (gracias a todos) Al final he elegido la solución XML. Particularmente no me gusta porque estorba hasta mis recursos Aplicaciones y me consideró seriamente el uso de la solución de interfaz, pero la solución XML funciona muy bien

Respuesta

20

Opción # 1 extender su clase AppConstants en cada proyecto

Mejor Opción # 2 recursos Uso de XML para definir las constantes

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
<item type="integer" name="app_id" format="integer">6</item> 
</resources> 

continuación, puede descargarlos por

Context.getResources().getInteger(R.integer.app_id); 

agregue el archivo xml a sus recursos en cada proyecto con solo los valores que necesita

+2

Si define los recursos con el mismo ID en su biblioteca y su aplicación se obtiene el valor de la aplicación si eso existe, de la biblioteca de lo contrario. Así que ese es un enfoque muy bueno para los valores que desea sobrescribir por aplicación. Como está utilizando el sistema de recursos, puede incluso hacer valores por configuración (paisaje vs retrato, etc.) – zapl

1

definirlos como de enumeración en su proyecto de biblioteca, como

public enum Planet { MERCURY, VENUS, MARS } 

androide adecuado toma otro enfoque, la temida interfaz constante, como,

interface Planets { 
    static final int MERCURY = 1; 
    static final int VENUS = 2; 
    ... 
} 

sin embargo, este es un anti-patrón java bien conocido (interfaz constante, y está cubierto i n detalle en Java efectivo, cito,

El patrón de interfaz constante es un uso deficiente de las interfaces. Que una clase use algunas constantes internamente es un detalle de implementación. La implementación de una interfaz constante ocasiona que este detalle de implementación se filtre a en la API exportada de la clase. No tiene ninguna consecuencia para los usuarios de que la clase implemente una interfaz constante. En el hecho , incluso puede confundirlos. Peor aún, representa un compromiso: si en una versión futura la clase se modifica para que ya no necesite para usar las constantes, todavía debe implementar la interfaz para asegurar la compatibilidad binaria . Si una clase no final implementa una interfaz constante , todas sus subclases tendrán sus espacios de nombres contaminados por las constantes en la interfaz.

si necesita las constantes tener valores int por alguna razón, y llamar a toString() en la enumeración no es suficiente, se puede dar la enumeración es una información extra, como,

public enum ZipCode { 
    LYNNWOOD(98036), SAN_JOSE(95112), ...; 

    private int zipCode; 

    private ZipCode(int zipCode) { this.zipCode = zipCode; } 

    public int getZipCode() { return zipCode; } 
} 

Nota que las enumeraciones son ligeramente menos efectivas que las constantes enteras, pero desde una organización de código y una perspectiva de claridad son muy superiores.

3

No sé de un gran esquema para hacer eso, pero sería sin duda trabajar de esta manera:

definir algunos clase base en la biblioteca de

// class, enum or whatever you want it to be. 
class BaseConstants { 
    // use some real singleton instead 
    public static final BaseConstants instance = new BaseConstants(); 

    // define those values - sadly static inheritance does not work 
    private static final int APP_ID = 0; 
    private static final int CURRENT_APP_ID_KEY = 24; 

    // so we have to do that via methods 
    protected int getAppId() { 
     return APP_ID; 
    } 
    protected int getAppIdKey() { 
     return CURRENT_APP_ID_KEY; 
    } 
} 

dejar que cada actividad que quiere algo implementación personalizada que

class App1Constants extends BaseConstants { 
    public static final App1Constants instance = new App1Constants(); 

    private final static int APP_ID = 1; 

    // want a different APP_ID here. 
    protected int getAppId() { 
     return APP_ID; 
    } 

    // getAppIdKey not implemented here, uses default 
} 

Use esa clase como contexto a las constantes para su biblioteca

class Library { 
    public static long getCurrentAppId(Context context, BaseConstants settings) { 
     return getLongPreference(context, settings.getAppIdKey(), settings.getAppId()); 
    } 
} 

actividades serían igual que

class myActivity extends Activity { 
    // each Activity can implement it's own constants class and overwrite only some values 
    private static final BaseConstants CONSTANTS = App1Constants.instance; 

    private void whatever() { 
     long appId = Library.getCurrentAppId(this, CONSTANTS); 
    } 
} 

class myActivity2 extends Activity { 
    // or could just use the default ones 
    private static final BaseConstants CONSTANTS = BaseConstants.instance; 

    private void whatever() { 
     long appId = Library.getCurrentAppId(this, CONSTANTS); 
    } 
} 

Ese esquema es un poco feo pero trabajaría al menos

Cuestiones relacionadas