Qu'est-ce qu'Android Lint et comment vous aide-t-il à écrire du code pris en charge?

Qu'est-ce qu'Android Lint et comment vous aide-t-il à écrire du code pris en charge?


Lorsque le développeur ne fait pas assez attention, les choses peuvent très mal se passer. Par exemple, les omissions classiques des développeurs sont l'utilisation d'une nouvelle version de l'API, qui n'est pas compatible avec l'ancien code, l'exécution d'actions qui nécessitent des autorisations utilisateur spéciales et des lacunes dans la localisation de l'application. Et ce ne sont que quelques-uns d'entre eux.


De plus, Java et Kotlin, comme tout autre langage de programmation, ont leurs propres constructions qui peuvent conduire à de mauvaises performances.


Bonjour charpie


Nous utilisons un outil appelé Lint (ou Linter) pour éviter de tels problèmes. Lint est un outil d'analyse de code statique qui aide les développeurs à détecter les problèmes potentiels avant la compilation du code. Lint effectue plusieurs vérifications du code source, qui peuvent détecter des problèmes tels que des variables inutilisées ou des arguments de fonction, la simplification des conditions, une portée incorrecte, des variables ou des fonctions non définies, du code mal optimisé, etc. Lorsque nous parlons de développement Android, il y a des centaines de contrôles Lint prêts à l'emploi.


Mais parfois, nous devons trouver des problèmes spécifiques dans notre code qui ne sont pas couverts par ces vérifications existantes.


Bonjour chèques personnalisés Lint


Avant de commencer le codage, définissons notre objectif et voyons comment l'implémenter étape par étape à l'aide de l'API Lint. Le but est de créer une vérification pour détecter un appel de méthode incorrect pour un objet. L'idée de ce test est de déterminer si la méthode d'installation de l'écouteur sur le composant View est celle qui interrompra plusieurs clics consécutifs sur le composant afin que nous puissions éviter d'ouvrir la même activité ou d'accéder au réseau plusieurs fois.


Les contrôles utilisateur Lint sont écrits dans le cadre du module Java (ou Kotlin) standard. La façon la plus simple de commencer est de créer un projet simple basé sur Gradle (il ne doit pas nécessairement s'agir d'un projet Android).


Ajoutez ensuite les dépendances Lint. Dans le fichier build.gradle de votre module, ajoutez:


 compileOnly "com.android.tools.lint:lint-api:$lintVersion" compileOnly "com.android.tools.lint:lint-checks:$lintVersion" 

Il y a maintenant une astuce que j'ai apprise lors de mes recherches sur ce sujet. lintVersion doit être gradlePluginVersion + 23.0.0 . gradlePluginVersion est une variable définie dans le fichier build.gradle au niveau du projet. Et pour le moment, la dernière version stable est la 3.3.0. Cela signifie que lintVersion devrait être 26.3.0.


Chaque test de charpie se compose de 4 parties:


  • Le problème est le problème dans notre code que nous essayons d'éviter. Lorsque la vérification Lint échoue, cela est signalé au développeur.
  • Le détecteur est un outil de recherche de problèmes qui fournit l'API Lint.
  • Une implémentation est un domaine où un problème peut survenir (fichier source, fichier XML, code compilé, etc.).
  • Un registre est un registre de vérification Lint personnalisé qui sera utilisé avec un registre existant contenant des vérifications prédéfinies.

Implémentation


Commençons par créer une implémentation pour notre validation personnalisée. Chaque implémentation se compose d'une classe qui implémente un détecteur et une étendue.


 val correctClickListenerImplementation = Implementation(CorrectClickListenerDetector::class.java, Scope.JAVA_FILE_SCOPE) 

N'oubliez pas que Scope.JAVA_FILE_SCOPE fonctionnera également pour les classes Kotlin.


Le problème


L'étape suivante consiste à utiliser cette implémentation pour déterminer le problème. Chaque problème se compose de plusieurs parties:


  • ID est un identifiant unique.
  • Description - un bref énoncé (5-6 mots) du problème.
  • Explication Une explication complète d'un problème avec une suggestion sur la façon de résoudre ce problème.
  • Catégorie - la catégorie du problème (performances, traduction, sécurité, etc.).
  • Priorité - L'importance du problème, dans la plage de 1 à 10, où 10 est le plus élevé. Ceci sera utilisé pour trier les problèmes dans le rapport créé lors du lancement de Lint.
  • Gravité - gravité du problème (fatal, erreur, avertissement, information ou ignorance).
  • Une implémentation est une implémentation qui sera utilisée pour détecter ce problème.

 val ISSUE_CLICK_LISTENER = Issue.create( id = "UnsafeClickListener", briefDescription = "Unsafe click listener", explanation = """" This check ensures you call click listener that is throttled instead of a normal one which does not prevent double clicks. """.trimIndent(), category = Category.CORRECTNESS, priority = 6, severity = Severity.WARNING, implementation = correctClickListenerImplementation ) 

Détecteur


L'API Lint propose des interfaces pour chaque domaine que vous pouvez définir dans une implémentation. Chacune de ces interfaces fournit des méthodes que vous pouvez remplacer et accéder aux parties du code qui vous intéressent.


  • UastScanner - Fichiers Java ou Kotlin (UAST - Unified Abstract Syntax Tree ( arbre de syntaxe abstraite unifiée russe)).
  • ClassScanner - fichiers compilés (bytecode).
  • BinaryResourceScanner - ressources binaires telles que les bitmaps ou res/raw fichiers res/raw .
  • ResourceFolderScanner - dossiers de ressources (pas de fichiers spécifiques en eux).
  • XmlScanner - Fichiers XML.
  • GradleScanner - Fichiers Gradle.
  • OtherFileScanner - tout le reste.

De plus, la classe Detector est une classe de base qui a des implémentations vides de toutes les méthodes fournies par chacune des interfaces ci-dessus, vous n'avez donc pas besoin d'implémenter l'interface complète au cas où vous auriez besoin d'une seule méthode.


Nous sommes maintenant prêts à implémenter un détecteur qui vérifiera l'appel de méthode correct pour l'objet.


 private const val REPORT_MESSAGE = "Use setThrottlingClickListener" /** *   ,        *     ,      . */ class CorrectClickListenerDetector : Detector(), Detector.UastScanner { /** * ,  ,      . *         , *          , *      ,   . */ override fun getApplicableUastTypes(): List<Class<out UElement>>? { return listOf<Class<out UElement>>(UCallExpression::class.java) } /** *      UAST,    , *    UAST   .    UElementHandler, *   ,     , *    ,  , , ,   .. *        ,    *    .     —  ,   *   ,    ,       . */ override fun createUastHandler(context: JavaContext): UElementHandler? { return object: UElementHandler() { override fun visitCallExpression(node: UCallExpression) { if (node.methodName != null && node.methodName?.equals("setOnClickListener", ignoreCase = true) == true) { context.report(ISSUE_CLICK_LISTENER, node, context.getLocation(node), REPORT_MESSAGE, createFix()) } } } } /** *    ,    *   IDE,      . */ private fun createFix(): LintFix { return fix().replace().text("setOnClickListener").with("setThrottlingClickListener").build() } } 

Le registre


La dernière chose que nous devons faire est d'ajouter des problèmes à notre registre et d'indiquer à Lint qu'il existe un registre de problèmes spécial qu'il doit utiliser avec le registre standard.


 class MyIssueRegistry : IssueRegistry() { override val issues: List<Issue> = listOf(ISSUE_CLICK_LISTENER) } 

Au niveau du module build.gradle :


 jar { manifest { attributes("Lint-Registry-v2": "co.infinum.lint.MyIssueRegistry") } } 

co.infinum.lint est un package de la classe MyIssueRegistry . Vous pouvez maintenant exécuter la tâche jar à l'aide du script gradlew , et la bibliothèque devrait apparaître dans le répertoire build/libs .


Voici un autre exemple de vérification utilisateur Lint, où vous pouvez voir comment traiter les fichiers XML.


Utiliser


Votre nouveau chèque Lint est prêt à être utilisé dans le projet. Si cette vérification peut être appliquée à tous les projets, vous pouvez la placer dans le dossier ~/.android/lint (vous pouvez la créer si elle n'existe pas déjà).


De plus, vous pouvez placer votre chèque dans un module séparé de votre projet et activer ce module comme toute autre dépendance à l'aide de la méthode lintChecks .


Est-ce que ça vaut le coup?


Lint est un très bon outil que tout développeur devrait utiliser. Être capable de détecter précocement des problèmes potentiels avec votre code est très utile. Bien que les chèques personnalisés ne soient pas faciles à écrire, principalement en raison de la complexité de l'API, ils en valent vraiment la peine et peuvent vous faire économiser beaucoup de temps et d'efforts à l'avenir.

Source: https://habr.com/ru/post/fr456272/


All Articles