2012-03-18 1 views
13

Sto creando un progetto di libreria per un numero di app Android. Le applicazioni hanno tutte alcune funzionalità comuni che desidero includere nel progetto di libreria, ma le funzioni di progetto biblioteca richiedere l'uso di applicazione costanti specificheAndroid, il modo migliore per fornire costanti specifiche per app in un progetto di libreria?

Così sto cercando un modo per fornire le funzioni di libreria con i nomi delle costanti e consentire ogni applicazione definirli

un esempio di una specifica costante applicazione e come viene utilizzato nel progetto libreria

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

Questo è solo un esempio di circa 60 costanti che devono essere definiti per ciascun app per un gran numero di funzioni di libreria

Ovviamente mi sarebbe normalmente solo importare/include il file app_constants.java progetto specifico, ma questo non è possibile in file di progetto biblioteca in quanto non ha la minima idea su applicazioni specifiche (giustamente)

Così qual è il modo migliore per fare in modo che ogni app specifica prevalga sulle costanti?

Aggiornamento ho preso un lungo periodo di tempo di decidere su quale delle risposte superbe Sono stato fornito con la migliore adatta alle mie esigenze (grazie a tutti) Alla fine ho scelto la soluzione xml. Non mi piace particolarmente perché ingombra le mie risorse applicazioni e ho seriamente in considerazione l'utilizzo della soluzione di interfaccia ma la soluzione xml funziona bene

risposta

20

Opzione # 1 estendere la vostra classe AppConstants in ogni progetto

migliore opzione # 2 risorse Utilizzare XML per definire le costanti

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

allora potete recuperarli da

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

aggiungi il file xml alle tue risorse in ogni progetto con solo i valori che ti servono diversi

+2

Se si definiscono le risorse con lo stesso ID nella libreria e l'applicazione si ottiene il valore dall'applicazione se esiste, dalla libreria altrimenti. Questo è un approccio davvero carino per i valori che si desidera sovrascrivere per applicazione. Dal momento che sta usando il sistema delle risorse puoi persino fare dei valori per configurazione (orizzontale, verticale, ecc.) – zapl

1

definirli come enum è nel vostro progetto di libreria, come

public enum Planet { MERCURY, VENUS, MARS } 

android corretta prende un altro approccio, la temuta costante interfaccia, come,

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

tuttavia, questo è un noto java anti-modello (interfaccia costante, ed è coperto i n dettaglio in Java efficace, cito,

Il modello di interfaccia costante è un uso scadente delle interfacce. Che una classe utilizzi alcune costanti internamente è un dettaglio di implementazione. L'implementazione di un'interfaccia costante fa sì che i dettagli di questa implementazione sfuggano a nell'API esportata della classe. Non è una conseguenza per gli utenti di una classe che la classe implementa un'interfaccia costante. Nel fatto , potrebbe persino confonderli. Peggio ancora, rappresenta un impegno: se in una versione futura la classe viene modificata in modo che non sia più necessario utilizzare le costanti , è comunque necessario implementare l'interfaccia per garantire la compatibilità binaria . Se una classe non definitiva implementa un'interfaccia costante , tutte le sue sottoclassi avranno i loro spazi dei nomi inquinati da dalle costanti nell'interfaccia.

se avete bisogno le costanti di avere valori int per qualche ragione, e chiamando toString() sul enum non è sufficiente, si può dare l'enumerazione di informazioni extra come,

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

    private int zipCode; 

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

    public int getZipCode() { return zipCode; } 
} 

Nota quelle enum sono leggermente meno performanti delle costanti intere, ma da una prospettiva di organizzazione e chiarezza del codice sono di gran lunga superiori.

3

Non so di un grande schema per farlo, ma sarebbe certamente lavorare in questo modo:

definire alcune classe base nella libreria

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

lasciare che ogni attività che vuole qualcosa di implementare personalizzato che

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 
} 

utilizzare tale classe come contesto per le costanti per la vostra biblioteca

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

attività sarebbero in questo modo

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

Questo schema è una specie di brutto ma sarebbe lavorare almeno