2016-02-25 4 views
32

Ich versuche @IntDef Annotation in Android-Entwicklung zu implementieren.Android - Ist es in Ordnung, @IntDef-Werte in @interface zu setzen?

Erste Methode: es sieht gut aus mit der Definition in einer Constant.java Klasse getrennt:

public class Constant { 
    @IntDef(value={SORT_PRICE, SORT_TIME, SORT_DURATION}) 
    @Retention(RetentionPolicy.SOURCE) 
    public @interface SortType{} 
    public static final int SORT_PRICE = 0; 
    public static final int SORT_TIME = 1; 
    public static final int SORT_DURATION = 2; 
} 

Verbrauch:

@Constant.SortType int sortType = Constant.SORT_PRICE; 

Aber die Dinge viel unordentlicher bekommen, wenn es mehrere Definition ist (zB Usertype , StoreType, usw.) in einer Datei.

Zweite Methode: So kam ich mit so etwas zu trennen Werte zwischen Definition bis:

public class Constant { 
    @IntDef(value={SortType.SORT_PRICE, SortType.SORT_TIME, SortType.SORT_DURATION}) 
    @Retention(RetentionPolicy.SOURCE) 
    public @interface SortTypeDef{} 

    public static class SortType{ 
     public static final int PRICE = 0; 
     public static final int TIME = 1; 
     public static final int DURATION = 2; 
    } 
} 

Verbrauch:

@Constant.SortTypeDef int sortType = Constant.SortType.PRICE; 

Aber wie Sie sehen können, habe ich zwei verschiedene Namen erstellt dafür: SortTypeDef und SortType

Dritte Met hod: Ich habe versucht, die Liste der möglichen Werte innerhalb @interface zu bewegen:

public class Constant { 
    @IntDef(value={SortType.SORT_PRICE, SortType.SORT_TIME, SortType.SORT_DURATION}) 
    @Retention(RetentionPolicy.SOURCE) 
    public @interface SortType{ 
     int PRICE = 0; 
     int TIME = 1; 
     int DURATION = 2; 
    } 
} 

Nutzungs

@Constant.SortType int sortType = Constant.SortType.PRICE; 

Während es funktioniert, ich weiß nicht, was ist der Nachteil. Ist es in Ordnung, die möglichen Werte von @IntDef in @interface zu setzen? Gibt es Leistungsunterschiede zwischen den drei oben genannten Methoden?

+0

Haben Sie gefunden eine Lösung für diese Frage? Ich frage mich das gleiche jetzt ... –

+2

@IgorGanapolsky noch nicht, aber ich verwende weiterhin die dritte Methode auf den Produktionscode und bis jetzt kein Problem. Ich denke, der beste Weg, dies zu überprüfen, ist das Profiling (Nutzung, Anzahl der Konstanten usw.). –

+0

Die IntDef-Annotation hat nur RetentionPolicy.SOURCE und wird daher nur von Compiler-Annotationsprozessoren verwendet. Es ist nicht möglich, dass es sich auf die Laufzeitleistung auswirkt, es sei denn, der Annotationsprozessor tut etwas sehr Esoterisches, z. B. Bytecode-Weben oder Codegenerierung, um Laufzeitprüfungen in den Code einzufügen. –

Antwort

0

scheint ein guter Ort für einen emum ...

public enum SortEnum { DAUER, PREIS, ZEIT; }

+0

idk, ich habe enum seit ich https://www.youtube.com/watch?v=Hzs6OBcvNQE sah. Zugegeben, das Video ist 2 Jahre alt und viele Dinge haben sich möglicherweise geändert. –

+0

IntDefs wurden speziell für Enum-Ersetzungen in ressourcenbeschränkten Systemen entwickelt. Die Empfehlung, sie durch Enums zu ersetzen, beantwortet weder die Frage noch trägt sie zum Gespräch bei. – TBridges42

+1

Die Enum-Probleme in Android waren mir nicht bekannt, bis Ahmad darauf hinwies. Ich benutze Java für immer, aber nicht Android bis vor kurzem und es schien mir, dass das OP ein Anti-Pattern implementiert hat. Aber seit ich nach etwas gesucht habe, was bei Enums auf Android ein Problem zu sein scheint, werde ich sie vermeiden und IntDefs ausprobieren. – NinePlanFailed

1

Ich kam hier in der Hoffnung zu finden, warum die Android-Dokumente zeigen Ihre erste Methode, aber die dritte Methode hat für mich in Produktionscode für Monate gut funktioniert. Ich habe keinen Grund gesehen, es nicht so zu machen. Wie Sie gesagt haben, bereinigt es den Namespace, wenn Sie mehrere Sätze verwandter Konstanten haben.

3

Um Ihre dritte Methode zu arbeiten, sollten Sie values wie in der Schnittstelle benennen. ich verwendet, um Ihren Code und machen es funktioniert:

public class Constant { 
    @IntDef(value = {SortType.PRICE, SortType.TIME, SortType.DURATION}) 
    @Retention(RetentionPolicy.SOURCE) 
    @interface SortType { 
     int PRICE = 0; 
     int TIME = 1; 
     int DURATION = 2; 
    } 
} 

Oder

public class Constant { 
    @IntDef(value = {SortType.SORT_PRICE, SortType.SORT_TIME, SortType.SORT_DURATION}) 
    @Retention(RetentionPolicy.SOURCE) 
    @interface SortType { 
     int SORT_PRICE = 0; 
     int SORT_TIME = 1; 
     int SORT_DURATION = 2; 
    } 
} 

Verwendung für die zweite:

@Constant.SortType int sortType = Constant.SortType.SORT_DURATION; 

eine Auswahl, sollten beide arbeiten.

3

Kurze Antwort: Für einfache Projekte ist es in Ordnung, aber für komplexere ist die erste Methode bevorzugt.

Lange Antwort: Obwohl Bytecode für sortType in allen drei Fällen identisch ist, gibt es einen Unterschied. Der Schlüssel liegt in der Annotation Retention, in der die Aufbewahrungsrichtlinie auf SOURCE festgelegt ist. Das bedeutet, dass Ihre SortType Annotation "to be discarded by the compiler" ist, so dass der Bytecode für die Annotation selbst nicht generiert wird.

Die erste Methode definiert reguläre statische Felder außerhalb der Annotationen, für die der reguläre Bytecode generiert wird. Die zweiten und dritten Fälle definieren Konstanten in Annotationen, und Bytecode für die Konstanten wird nicht generiert.

Wenn der Compiler Zugriff auf die Quelldatei mit Ihrer SortType Deklaration hat, ist eine der beiden Methoden in Ordnung, und der Bytecode für sortType ist identisch. Wenn auf Quellcode nicht zugegriffen werden kann (z. B. wenn Sie nur die Bibliothek kompiliert haben), kann auf die Annotation nicht zugegriffen werden. Für den ersten Ansatz ist nur die Annotation selbst nicht zugänglich, aber für die letzteren sind Konstantenwerte ebenfalls nicht zugänglich.

Ich bevorzuge die dritte Methode als die sauberste und strukturiert. Ich war es bis zu einem Tag, an dem ich auf ein Problem stieß: Als ich begann, Espresso-Tests für diesen Code zu schreiben, hatte der Compiler keinen Zugriff auf den Quellcode, der die Anmerkung definierte. Ich musste entweder auf die kanonische Deklaration IntDef umschalten oder anstelle von symbolischen Konstanten ganzzahlige Werte für den Test verwenden.

So lautet das Fazit ist:

  • -Stick auf die kanonische Weise, es sei denn Ihre Anmerkung zu Ihrem Code interne und Sie beziehen sich nicht von irgendwo anders es, einschließlich Tests
Verwandte Themen