|
| 1 | +--- |
| 2 | +author: Florian |
| 3 | +cover: android-simple-banner |
| 4 | +date: '2016-10-03' |
| 5 | +tags: |
| 6 | +- Android |
| 7 | +- XML |
| 8 | +- Tools |
| 9 | +- Design |
| 10 | +title: 'Android Annotations : Abusez-en !' |
| 11 | +url: /2016/10/03/android-annotations-lib/ |
| 12 | +aliases: /2016/10/03/android-annotations-lib.html |
| 13 | +draft: true |
| 14 | +--- |
| 15 | + |
| 16 | +Dans le lot des https://developer.android.com/topic/libraries/support-library/index.html[supports librairies] que propose Google pour le développement Android (principalement pour la compatibilité des certains composants sur des anciennes versions de l'OS) il y en a une qui de prime abord ne va pas beaucoup servir c'est `support-annotations`. |
| 17 | + |
| 18 | +[%hardbreaks] |
| 19 | + |
| 20 | +En effet cette librairie ne contient pas grand chose en terme de classes ni de http://www.methodscount.com/?lib=com.android.support%3Asupport-annotations%3A24.2.1[méthodes]. En revanche elle possède de nombreuses annotations (d'où son nom...). Le comble c'est que presque toutes ces annonations sont définie en tant que `@Retention(CLASS)`, c'est-à-dire qu'elles seront supprimées par le compilateur lors de la génération des fichiers _.classes_. |
| 21 | +À quoi peuvent-elles servir ? Et bien c'est le propre des annotations, elles servent à apporter des informations sur des portions de code et éventuellement donner quelques instructions au compilateur. L'un des exemples le plus connu est _@Deprecated_ que vous devez cotoyer tous les jours. Cette annotation a pour seul but d'informer le développeur qu'il est fortement déconseillé d'utilser cette méthode. |
| 22 | + |
| 23 | +L'avantage d'utiliser les `support-annotations` est qu'Android Studio connait leur signification et donc vas pouvoir highliter des portions de code en rapport avec celles-ci lorsqu'un comportement attendu n'est pas respecté. |
| 24 | + |
| 25 | +Faisons un petit tour des https://developer.android.com/reference/android/support/annotation/package-summary.html[annotations présentes dans `support-annotations`] et de leur intégration dans Android Studio |
| 26 | + |
| 27 | + |
| 28 | +# @Nullable / @NonNull |
| 29 | + |
| 30 | +Le couple d'annotation le plus connu est probablement @Nullable et @NonNull, car déjà présent depuis un certain temps dans différents packages comme https://www.jetbrains.com/help/idea/2016.2/nullable-and-notnull-annotations.html[Intellij] ou http://mvnrepository.com/artifact/javax.annotation/javax.annotation-api/1.3[javax.annotations]. |
| 31 | + |
| 32 | +Annoter une méthode @Nullable permet d'indiquer que le retour de celle-ci peut être _null_ et donc qu'il est fort préférable de procéder à un null check avant d'utiliser l'objet retourné. Le @NonNull permet lui d'assurer que le résultat est toujours un objet valide. |
| 33 | + |
| 34 | +{lt}div style="text-align : center"{gt} |
| 35 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_nullable.png" data-lightbox="1" title="Warning sur un retour @Nullable"{gt} |
| 36 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_nullable_min.png" alt="Warning sur un retour @Nullable"/{gt} |
| 37 | +{lt}/a{gt} |
| 38 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_notnull.png" data-lightbox="1" title="Warning sur une methode @NonNull"{gt} |
| 39 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_notnull_min.png" alt="Warning sur une methode @NonNull"/{gt} |
| 40 | +{lt}/a{gt} |
| 41 | +{lt}/div{gt} |
| 42 | + |
| 43 | +{lt}br/{gt} |
| 44 | + |
| 45 | +# @<Any>Ref |
| 46 | + |
| 47 | +Le groupe d'annotation suivant est probablement celui que j'utilise le plus souvent est le `@...Ref`. |
| 48 | + |
| 49 | +Et oui étant donné que toutes les références des ressources sont des `int` lorsqu'elles sont générées dans votre class _R_ il est difficile de les différencier lorsqu'on en passe une en paramètre de méthode. |
| 50 | +Et bien avec un `@ColorRes int myColor`, Android studio s'occupera de vous avertir si la valeur passée ne correspond pas à une ressource du type `color`. |
| 51 | + |
| 52 | +{lt}div style="text-align : center"{gt} |
| 53 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_stringres.png" data-lightbox="1" title="Warning sur un paramètre @StringRes"{gt} |
| 54 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_stringres_min.png" alt="Warning sur un paramètre @StringRes"/{gt} |
| 55 | +{lt}/a{gt} |
| 56 | +{lt}/div{gt} |
| 57 | + |
| 58 | +{lt}br/{gt} |
| 59 | + |
| 60 | +La liste (non complète) des ressources que vous pouvez contrôler : |
| 61 | + |
| 62 | +- `ColorRes` |
| 63 | +- `DimenRes` |
| 64 | +- `DrawableRes` |
| 65 | +- `IdRes` |
| 66 | +- `StringRes` |
| 67 | + |
| 68 | +# @CallSuper |
| 69 | +Je l'ai découverte récement et je trouve qu'elle est d'une grande aide. Étant donné l'importance du cycle de vie de chaque élément dans Android |
| 70 | +il est indispensble de s'assurer que chaque méthode est appelée au bon moment. |
| 71 | +Et lorsque qu'il y a un peu de refactor il arrive vite d'oublier d'appeler le super d'une méthode surchargée. Maintenant vous en serez averti ! |
| 72 | + |
| 73 | +{lt}div style="text-align : center"{gt} |
| 74 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_callsuper.png" data-lightbox="1" title="Warning sur un appel super manquant"{gt} |
| 75 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_callsuper_min.png" alt="Warning sur un appel super manquant"/{gt} |
| 76 | +{lt}/a{gt} |
| 77 | +{lt}/div{gt} |
| 78 | + |
| 79 | +{lt}br/{gt} |
| 80 | + |
| 81 | + |
| 82 | +# @RequirePermission |
| 83 | +Pour être sur de ne pas oublier une permission dans le `manifest.xml` cette annotation permettra (sur une classe ou une méthode) de vous rappeler explicitement quelles sont celles dont vous avez besoin. |
| 84 | + |
| 85 | +On peut d'ailleurs voir le warning d'android studio en créant un sample project et en démarrant une nouvelle activity avec un `Intent.ACTION_CALL`. |
| 86 | + |
| 87 | + |
| 88 | +{lt}div style="text-align : center"{gt} |
| 89 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_permission.png" data-lightbox="1" title="Warning sur une permission manquante"{gt} |
| 90 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_permission_min.png" alt="Warning sur une permission manquante"/{gt} |
| 91 | +{lt}/a{gt} |
| 92 | +{lt}/div{gt} |
| 93 | + |
| 94 | +{lt}br/{gt} |
| 95 | + |
| 96 | +# @StringDef |
| 97 | +Lorsque l'on dev pour Android on doit savoir que https://www.youtube.com/watch?v=Hzs6OBcvNQE[les enums sont a proscrire] et du coup c'est embetant, car c'est tout de même bien pratique. |
| 98 | +La parade est donc de passer par une liste de constantes et de créer une nouvelle annotation qui limitera les valeurs attendu, comme ceci : |
| 99 | + |
| 100 | +[source,java] |
| 101 | +----- |
| 102 | +public final static String Constant.TROOPER_VINCENT = "VM"; |
| 103 | +public final static String Constant.TROOPER_JORIS = "JP"; |
| 104 | +public final static String Constant.TROOPER_BENJAMIN = "BC"; |
| 105 | +
|
| 106 | +@StringDef({ |
| 107 | + Constant.TROOPER_VINCENT, |
| 108 | + Constant.TROOPER_JORIS, |
| 109 | + Constant.TROOPER_BENJAMIN, |
| 110 | +}) |
| 111 | +@Retention(RetentionPolicy.SOURCE) |
| 112 | +public @interface Trooper { |
| 113 | +} |
| 114 | +----- |
| 115 | + |
| 116 | +Et ensuite d'uiliser cette annotation a chaque fois que seulement une des valeurs précédent est autorisée. |
| 117 | + |
| 118 | +[source,java] |
| 119 | +----- |
| 120 | +public void getProject(@Trooper String currentTrooper){} |
| 121 | +----- |
| 122 | + |
| 123 | +Certes ce n'est pas aussi puissant qu'une enum, mais il faudra faire avec. |
| 124 | + |
| 125 | +{lt}div style="text-align : center"{gt} |
| 126 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_stringdef.png" data-lightbox="1" title="Warning sur un paramètre non attendu"{gt} |
| 127 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_stringdef_min.png" alt="Warning sur un paramètre non attendu"/{gt} |
| 128 | +{lt}/a{gt} |
| 129 | +{lt}/div{gt} |
| 130 | + |
| 131 | +{lt}br/{gt} |
| 132 | + |
| 133 | + |
| 134 | +# @Range |
| 135 | +Toujours dans l'idée d'éviter de créer des énum @IntRange permettra de spécifier un peu plus ce qu'une méthode attend en paramètre. |
| 136 | + |
| 137 | +{lt}div style="text-align : center"{gt} |
| 138 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_range.png" data-lightbox="1" title="Warning sur un paramètre hors limites"{gt} |
| 139 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_range_min.png" alt="Warning sur un paramètre hors limites"/{gt} |
| 140 | +{lt}/a{gt} |
| 141 | +{lt}/div{gt} |
| 142 | + |
| 143 | +{lt}br/{gt} |
| 144 | + |
| 145 | +Une variante `@FloatRange` est aussi disponible. |
| 146 | + |
| 147 | +# Lint |
| 148 | + |
| 149 | +Comme chacune des erreurs n'empèche pas la compilation du projet, un bon moyen de surveiller qu'il n'y a pas de violation aux règles mises en place grâce à toutes ces annotations, |
| 150 | +est de controler les rapports générer par lint |
| 151 | + |
| 152 | +{lt}div style="text-align : center"{gt} |
| 153 | +{lt}a class="inlineBoxes" href="/images/posts/2016-09_AndroidAnnotations/android_annotations_lint.png" data-lightbox="1" title="Exemple de rapport lint"{gt} |
| 154 | + {lt}img class="medium" src="/images/posts/2016-09_AndroidAnnotations/android_annotations_lint_min.png" alt="Exemple de rapport lint"/{gt} |
| 155 | +{lt}/a{gt} |
| 156 | +{lt}/div{gt} |
| 157 | + |
| 158 | +{lt}br/{gt} |
| 159 | + |
| 160 | + |
| 161 | +# L'ajouter dans son projet |
| 162 | + |
| 163 | +[source,groovy] |
| 164 | +----- |
| 165 | +dependencies { |
| 166 | + compile 'com.android.support:support-annotations:24.2.1' |
| 167 | +} |
| 168 | +----- |
| 169 | + |
| 170 | + |
| 171 | +### Liens |
| 172 | + |
| 173 | +https://developer.android.com/topic/libraries/support-library/features.html#annotations |
| 174 | + |
| 175 | +https://developer.android.com/studio/write/annotations.html |
| 176 | + |
| 177 | +https://developer.android.com/reference/android/support/annotation/package-summary.html |
| 178 | + |
| 179 | +https://github.com/fchauveau/blog-android-annotations/tree/master/app/src/main/java/com/codetroopers |
0 commit comments